本文介紹在iOS上集成Google和Apple三方登錄的開發(fā)指南。

Google登錄

  1. 創(chuàng)建項目
    1. 打開Google后臺,單擊左上角My Project,再在彈出框中單擊創(chuàng)建項目

      創(chuàng)建項目
    2. 接下來申請配置項目參數(shù),在集成開發(fā)界面中單擊Create an OAuth clientID按鈕。配置項目參數(shù)
    3. 選擇剛才創(chuàng)建的項目,選擇平臺iOS,輸入項目BundleID,成功之后會提示下載一個plist文件,里面包含了配置參數(shù)。plist
  2. Xcode工程配置

    在xcode工程的info.plist文件中配置url schemeURL Schemes參數(shù)填Google生成plist文件中的REVERSED_CLIENT_ID

    xcode

代碼示例

#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授權(quán)登錄
- (void)thirdAuthorizationLogin {
    id<ALBBOpenAccountSSOService> ssoService = ALBBService(ALBBOpenAccountSSOService);
    //初始化
    [ssoService setPlatform:OAAuthPlatformType_Google
                     appKey:IMSAuthPlatformGoogleAppKey
                  appSecret:nil
                redirectURL:nil];
    //三方賬號授權(quán)登錄
    [ssoService oauthWithPlatForm:OAAuthPlatformType_Google
                     presentingVC:self
                         delegate:self];
}

#pragma mark - SSODelegate

- (void)openAccountOAuthError:(NSError *)error Session:(ALBBOpenAccountSession *)session {
    if (error && error.code != -5) {
        //處理授權(quán)登錄錯誤
    }
}

@end
在AppDelegate里需要處理系統(tǒng)回調(diào),代碼示例如下所示
- (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登錄

項目配置

  • 在蘋果開發(fā)者網(wǎng)站,開通sign in with Apple。開通Sign in
  • 在Xcode中添加sign in with Apple。

    選中target,在Signing & Capabilities中點擊Capability選擇sign in with Apple。

    CapabilitySign 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授權(quán)登錄
- (void)handleAplleAuthrization {
    if (@available(iOS 13.0, *)) {
        // A mechanism for generating requests to authenticate users based on their Apple ID.
        // 基于用戶的Apple ID授權(quán)用戶,生成用戶授權(quán)請求的一種機制
        ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];
        // Creates a new Apple ID authorization request.
        // 創(chuàng)建新的AppleID 授權(quán)請求
        ASAuthorizationAppleIDRequest *request = appleIDProvider.createRequest;
        // The contact information to be requested from the user during authentication.
        // 在用戶授權(quán)期間請求的聯(lián)系信息
        request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];

        // A controller that manages authorization requests created by a provider.
        // 由ASAuthorizationAppleIDProvider創(chuàng)建的授權(quán)請求 管理授權(quán)請求的控制器
        ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
        // A delegate that the authorization controller informs about the success or failure of an authorization attempt.
        // 設(shè)置授權(quán)控制器通知授權(quán)請求的成功與失敗的代理
        controller.delegate = self;
        // A delegate that provides a display context in which the system can present an authorization interface to the user.
        // 設(shè)置提供 展示上下文的代理,在這個上下文中 系統(tǒng)可以展示授權(quán)界面給用戶
        controller.presentationContextProvider = self;
        // starts the authorization flows named during controller initialization.
        // 在控制器初始化期間啟動授權(quán)流
        [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]]) {
        // 用戶登錄使用現(xiàn)有的密碼憑證
        ASPasswordCredential *passwordCredential = authorization.credential;
        // 密碼憑證對象的用戶標(biāo)識 用戶的唯一標(biāo)識
        NSString *user = passwordCredential.user;
        // 密碼憑證對象的密碼
        NSString *password = passwordCredential.password;
        [mStr appendString:user?:@""];
        [mStr appendString:password?:@""];
        [mStr appendString:@"\n"];
        NSLog(@"mStr:%@", mStr);
    } else {
        NSLog(@"授權(quán)信息均不符");
        mStr = [@"授權(quán)信息均不符" 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 = @"用戶取消了授權(quán)請求";
            break;
        case ASAuthorizationErrorFailed:
            errorMsg = @"授權(quán)請求失敗";
            break;
        case ASAuthorizationErrorInvalidResponse:
            errorMsg = @"授權(quán)請求響應(yīng)無效";
            break;
        case ASAuthorizationErrorNotHandled:
            errorMsg = @"未能處理授權(quán)請求";
            break;
        case ASAuthorizationErrorUnknown:
            errorMsg = @"授權(quán)請求失敗未知原因";
            break;
    }

    if (errorMsg) {
        return;
    }

    NSLog(@"controller requests:%@", controller.authorizationRequests);
}

#pragma mark - ASAuthorizationControllerPresentationContextProviding

- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller  API_AVAILABLE(ios(13.0)){

    NSLog(@"調(diào)用展示window方法:%s", __FUNCTION__);
    // 返回window
    return self.view.window;
}
#endif

#pragma mark - SSODelegate

- (void)openAccountOAuthError:(NSError *)error Session:(ALBBOpenAccountSession *)session {
    if (error && error.code != -5) {
        //處理授權(quán)登錄錯誤
    }
}

@end
在AppDelegate里需要處理系統(tǒng)回調(diào),代碼示例如下所示
- (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];

}