Integrate Google and Apple third-party logon for iOS

Updated at:

This topic describes how to integrate Google and Apple third-party logon for iOS.

Google logon

  1. Create a project
    1. Go to the Google console. In the upper-left corner, click My Project, and then click NEW PROJECT in the dialog box that appears.

    2. Next, configure the project parameters. On the integration development page, click the Create an OAuth clientID button.
    3. Select the project that you just created. Set the platform to iOS and enter the project BundleID. After the configuration is successful, you are prompted to download a plist file that contains the configuration parameters.
  2. Configure the Xcode project

    In the info.plist file of your Xcode project, configure the url scheme. Set the URL Schemes parameter to the value of REVERSED_CLIENT_ID from the plist file generated by Google.

Code example

#import <ALBBOpenAccountSSO/ALBBOpenAccountSSOService.h>
#import <ALBBOpenAccountCloud/ALBBOpenAccountSDK.h>

// The CLIENT_ID from the plist file generated by Google.
static NSString * const IMSAuthPlatformGoogleAppKey = @"xxxx.apps.googleusercontent.com";

@implementation GoogleLoginDemo

- (instancetype)init {
    self = [super init];
    if (self) {
          // Logon success notification.
        [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;
}

// Initiate Google authorization logon.
- (void)thirdAuthorizationLogin {
    id<ALBBOpenAccountSSOService> ssoService = ALBBService(ALBBOpenAccountSSOService);
    // Initialization.
    [ssoService setPlatform:OAAuthPlatformType_Google
                     appKey:IMSAuthPlatformGoogleAppKey
                  appSecret:nil
                redirectURL:nil];
    // Third-party account authorization logon.
    [ssoService oauthWithPlatForm:OAAuthPlatformType_Google
                     presentingVC:self
                         delegate:self];
}

#pragma mark - SSODelegate

- (void)openAccountOAuthError:(NSError *)error Session:(ALBBOpenAccountSession *)session {
    if (error && error.code != -5) {
        // Handle authorization logon errors.
    }
}

@end
Handle system callbacks in 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 logon

Project configuration

  • On the Apple Developer website, enable Sign in with Apple.
  • In Xcode, add Sign in with Apple.

    Select the target. On the Signing & Capabilities tab, click Capability and select Sign in with Apple.

Code example

#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) {
          // Logon success notification.
        [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;
}

// Initiate Apple authorization logon.
- (void)handleAplleAuthrization {
    if (@available(iOS 13.0, *)) {
        // A mechanism for generating requests to authenticate users based on their Apple ID.
        ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];
        // Creates a new Apple ID authorization request.
        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.
        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]]) {
        // The user logs on using 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);
        // Log on with an Apple account.
        [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]]) {
        // The user logs on using an existing password credential.
        ASPasswordCredential *passwordCredential = authorization.credential;
        // The user identifier of the password credential object. This is the unique identifier of the user.
        NSString *user = passwordCredential.user;
        // The password of the password credential object.
        NSString *password = passwordCredential.password;
        [mStr appendString:user?:@""];
        [mStr appendString:password?:@""];
        [mStr appendString:@"\n"];
        NSLog(@"mStr: %@", mStr);
    } else {
        NSLog(@"Authorization information does not match");
        mStr = [@"Authorization information does not match" mutableCopy];
    }
}

- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error  API_AVAILABLE(ios(13.0)){

    NSLog(@"%s", __FUNCTION__);
    NSLog(@"Error message: %@", error);
    NSString *errorMsg = nil;
    switch (error.code) {
        case ASAuthorizationErrorCanceled:
            errorMsg = @"The user canceled the authorization request";
            break;
        case ASAuthorizationErrorFailed:
            errorMsg = @"The authorization request failed";
            break;
        case ASAuthorizationErrorInvalidResponse:
            errorMsg = @"The authorization request response is invalid";
            break;
        case ASAuthorizationErrorNotHandled:
            errorMsg = @"The authorization request could not be handled";
            break;
        case ASAuthorizationErrorUnknown:
            errorMsg = @"The authorization request failed for an unknown reason";
            break;
    }

    if (errorMsg) {
        return;
    }

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

#pragma mark - ASAuthorizationControllerPresentationContextProviding

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

    NSLog(@"Call the method to display the window: %s", __FUNCTION__);
    // Return the window.
    return self.view.window;
}
#endif

#pragma mark - SSODelegate

- (void)openAccountOAuthError:(NSError *)error Session:(ALBBOpenAccountSession *)session {
    if (error && error.code != -5) {
        // Handle authorization logon errors.
    }
}

@end
Handle system callbacks in 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];

}