本文介绍在iOS上集成Google和Apple三方登录的开发指南。
Google登录
- 创建项目
- Xcode工程配置
在xcode工程的
info.plist
文件中配置url scheme
,URL Schemes
参数填Google生成plist
文件中的REVERSED_CLIENT_ID
。
代码示例
#import <ALBBOpenAccountSSO/ALBBOpenAccountSSOService.h>
#import <ALBBOpenAccountCloud/ALBBOpenAccountSDK.h>
//Google生成plist文件中的CLIENT_ID
static NSString * const IMSAuthPlatformGoogleAppKey = @"xxxx.apps.googleusercontent.com";
@implementation GoogleLoginDemo
- (instancetype)init {
self = [super init];
if (self) {
//登录成功通知
[IMSNotification addObserverForName:ALBBOpenAccountNotificationUserLoggedIn object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
if (note.object != nil && ([note.object isEqualToString:ALBBOpenAccountNotificationTrigerByREG] || [note.object isEqualToString:ALBBOpenAccountNotificationTrigerByLogin])) {
}
}];
}
return self;
}
//拉起Google授权登录
- (void)thirdAuthorizationLogin {
id<ALBBOpenAccountSSOService> ssoService = ALBBService(ALBBOpenAccountSSOService);
//初始化
[ssoService setPlatform:OAAuthPlatformType_Google
appKey:IMSAuthPlatformGoogleAppKey
appSecret:nil
redirectURL:nil];
//三方账号授权登录
[ssoService oauthWithPlatForm:OAAuthPlatformType_Google
presentingVC:self
delegate:self];
}
#pragma mark - SSODelegate
- (void)openAccountOAuthError:(NSError *)error Session:(ALBBOpenAccountSession *)session {
if (error && error.code != -5) {
//处理授权登录错误
}
}
@end
在AppDelegate里需要处理系统回调,代码示例如下所示- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
NSString *sourceApplication = [options objectForKey:UIApplicationOpenURLOptionsSourceApplicationKey];
id annotation = [options objectForKey:UIApplicationOpenURLOptionsAnnotationKey];
return [ALBBService(ALBBOpenAccountSSOService) handleOpenUrl:url application:app
sourceApplication:sourceApplication annotation:annotation];
}
Apple登录
项目配置
- 在苹果开发者网站,开通sign in with Apple。
- 在Xcode中添加sign in with Apple。
选中target,在Signing & Capabilities中点击Capability选择sign in with Apple。
代码示例
#import <ALBBOpenAccountSSO/ALBBOpenAccountSSOService.h>
#import <ALBBOpenAccountCloud/ALBBOpenAccountSDK.h>
#import <IMSApiClient/IMSConfiguration.h>
#if __has_include(<AuthenticationServices/AuthenticationServices.h>)
#import "AuthenticationServices/AuthenticationServices.h"
#endif
@implementation AppleLoginDemo
- (instancetype)init {
self = [super init];
if (self) {
//登录成功通知
[IMSNotification addObserverForName:ALBBOpenAccountNotificationUserLoggedIn object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
if (note.object != nil && ([note.object isEqualToString:ALBBOpenAccountNotificationTrigerByREG] || [note.object isEqualToString:ALBBOpenAccountNotificationTrigerByLogin])) {
}
}];
}
return self;
}
//拉起Apple授权登录
- (void)handleAplleAuthrization {
if (@available(iOS 13.0, *)) {
// A mechanism for generating requests to authenticate users based on their Apple ID.
// 基于用户的Apple ID授权用户,生成用户授权请求的一种机制
ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];
// Creates a new Apple ID authorization request.
// 创建新的AppleID 授权请求
ASAuthorizationAppleIDRequest *request = appleIDProvider.createRequest;
// The contact information to be requested from the user during authentication.
// 在用户授权期间请求的联系信息
request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
// A controller that manages authorization requests created by a provider.
// 由ASAuthorizationAppleIDProvider创建的授权请求 管理授权请求的控制器
ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
// A delegate that the authorization controller informs about the success or failure of an authorization attempt.
// 设置授权控制器通知授权请求的成功与失败的代理
controller.delegate = self;
// A delegate that provides a display context in which the system can present an authorization interface to the user.
// 设置提供 展示上下文的代理,在这个上下文中 系统可以展示授权界面给用户
controller.presentationContextProvider = self;
// starts the authorization flows named during controller initialization.
// 在控制器初始化期间启动授权流
[controller performRequests];
}
}
#pragma mark - ASAuthorizationControllerDelegate
#if __has_include(<AuthenticationServices/AuthenticationServices.h>)
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)){
NSMutableString *mStr = [NSMutableString string];
if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
// 用户登录使用ASAuthorizationAppleIDCredential
ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential;
NSString *user = appleIDCredential.user;
NSString *familyName = appleIDCredential.fullName.familyName;
NSString *givenName = appleIDCredential.fullName.givenName;
NSString *email = appleIDCredential.email;
NSMutableString* nick = [[NSMutableString alloc]initWithCapacity:3];
if (givenName != nil) {
[nick appendString:givenName];
[nick appendString:@" "];
}
if (familyName != nil) {
[nick appendString:familyName];
}
NSDictionary* userInfo = @{@"nick":nick.length > 0? nick : user, @"email":@""};
NSString* identityToken = [[NSString alloc] initWithData:appleIDCredential.identityToken encoding:NSUTF8StringEncoding];
id<ALBBOpenAccountSSOService> ssoService = ALBBService(ALBBOpenAccountSSOService);
//苹果账号登录
[ssoService signInWithApple:self
clientId:[[NSBundle mainBundle] bundleIdentifier]
identityToken:identityToken
appKey:[IMSConfiguration sharedInstance].appKey
openId:user
userInfo:userInfo
delegate:self];
} else if ([authorization.credential isKindOfClass:[ASPasswordCredential class]]) {
// 用户登录使用现有的密码凭证
ASPasswordCredential *passwordCredential = authorization.credential;
// 密码凭证对象的用户标识 用户的唯一标识
NSString *user = passwordCredential.user;
// 密码凭证对象的密码
NSString *password = passwordCredential.password;
[mStr appendString:user?:@""];
[mStr appendString:password?:@""];
[mStr appendString:@"\n"];
NSLog(@"mStr:%@", mStr);
} else {
NSLog(@"授权信息均不符");
mStr = [@"授权信息均不符" mutableCopy];
}
}
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0)){
NSLog(@"%s", __FUNCTION__);
NSLog(@"错误信息:%@", error);
NSString *errorMsg = nil;
switch (error.code) {
case ASAuthorizationErrorCanceled:
errorMsg = @"用户取消了授权请求";
break;
case ASAuthorizationErrorFailed:
errorMsg = @"授权请求失败";
break;
case ASAuthorizationErrorInvalidResponse:
errorMsg = @"授权请求响应无效";
break;
case ASAuthorizationErrorNotHandled:
errorMsg = @"未能处理授权请求";
break;
case ASAuthorizationErrorUnknown:
errorMsg = @"授权请求失败未知原因";
break;
}
if (errorMsg) {
return;
}
NSLog(@"controller requests:%@", controller.authorizationRequests);
}
#pragma mark - ASAuthorizationControllerPresentationContextProviding
- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller API_AVAILABLE(ios(13.0)){
NSLog(@"调用展示window方法:%s", __FUNCTION__);
// 返回window
return self.view.window;
}
#endif
#pragma mark - SSODelegate
- (void)openAccountOAuthError:(NSError *)error Session:(ALBBOpenAccountSession *)session {
if (error && error.code != -5) {
//处理授权登录错误
}
}
@end
在AppDelegate里需要处理系统回调,代码示例如下所示- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
NSString *sourceApplication = [options objectForKey:UIApplicationOpenURLOptionsSourceApplicationKey];
id annotation = [options objectForKey:UIApplicationOpenURLOptionsAnnotationKey];
return [ALBBService(ALBBOpenAccountSSOService) handleOpenUrl:url application:app
sourceApplication:sourceApplication annotation:annotation];
}