Apple ID ログイン

Apple ログインは、サードパーティ ログインの一種、つまり Apple ID を使用したログインとみなすことができます。前提条件として、すでに Apple 開発者アカウントを持っているため、トピックに直接進みます。

アプリ ID を追加し
ここに画像の説明を挿入
、バンドル ID を入力します
ここに画像の説明を挿入
。「Apple でサインイン」にチェックを入れて
ここに画像の説明を挿入
キーを作成します。Apple
は公開キーと秘密キーのペアを OAuth クライアント シークレットとして使用します。クライアント シークレットは実際には署名された JWT です。次のステップApple に新しい秘密キーを登録することです。作成が完了すると、キーファイル
ここに画像の説明を挿入
が生成されます。Key IDダウンロードしたキー ファイルは実際にはファイルです.p8。ダブルクリックして、このファイル内の必要なキーを開きます。このファイルは非常に重要なので、一度しかダウンロードできません。正しく保存してください。
ここに画像の説明を挿入
ここに画像の説明を挿入

クライアントシークレット(Client Secret)を生成します。

Apple では、静的なクライアント キーではなく、秘密キーからクライアント キーを自分で取得することを要求しています。これらは、P-256 曲線と SHA256 ハッシュを使用した楕円曲線アルゴリズムを使用した JWT 標準を使用します。つまり、ES256JWT アルゴリズムが使用されます。一部の JWT ライブラリは楕円曲線メソッドをサポートしていないため、試し始める前にライブラリが楕円曲線をサポートしていることを確認してください。RubyJWT ライブラリはこのアルゴリズムをサポートしているため、それを使用してシークレットを生成します。

まず、Ruby がインストールされていることを確認し、コマンド ラインから次のコマンドを実行して JWT gem をインストールします。

gem install jwt

上記で準備したBundle ID、 、Team IDに従って、 (クライアント キー)を生成できます。ファイルを作成し、名前を付け、サフィックスをieに変更するだけですテンプレートの内容は以下の通りです。Key IDAuthKey_xxx.p8client_secrettxtsecret_gen.rbsecret_gen.rb

require 'jwt'

key_file = ''
team_id = ''
client_id = ''
key_id = ''

ecdsa_key = OpenSSL::PKey::EC.new IO.read key_file

headers = {
    
    
  'kid' => key_id
}

claims = {
    
    
	'iss' => team_id,
	'iat' => Time.now.to_i,
	'exp' => Time.now.to_i + 86400*180,
	'aud' => 'https://appleid.apple.com',
	'sub' => client_id,
}

token = JWT.encode claims, ecdsa_key, 'ES256', headers

puts token

このコードは、ES256 アルゴリズムを使用してクレームの少ない JWT を生成します。JWT は、Apple が許可する最大有効期間である 6 か月で期限切れになります。ユーザーが認証されるたびに新しいクライアント シークレット JWT を生成する場合は、より短い有効期限を使用する必要がありますが、これによりキーを 1 回生成すれば、サンプル アプリケーションで簡単に使用できるようになります。

ここでは、準備した 4 つのデータを使用します。これでコマンド ラインから実行できるようになり、JWT が出力されます。
ここに画像の説明を挿入

ruby xxx/xx/xx/secret_gen.rb

ここに画像の説明を挿入
これはeyJra.....RuAQ必要なクライアント キーであり、キーが有効であることを確認します。

プロジェクトで Apple サインインを構成する

まずヘッダー ファイルをインポートし#import <AuthenticationServices/AuthenticationServices.h>、次に Apple 認証ページを呼び出します。

    if (@available(iOS 13.0, *)) {
    
    

        ASAuthorizationAppleIDProvider *appleIdProvider = [[ASAuthorizationAppleIDProvider alloc] init];
        ASAuthorizationAppleIDRequest *authAppleIDRequest = [appleIdProvider createRequest];
        /*
         //慎用 ASAuthorizationPasswordRequest
         //当启用ASAuthorizationPasswordRequest且停止使用Apple ID(真机-设置-账户-密码与安全性-使用您Apple ID的App-App列表-停止使用 Apple ID, 如果KeyChain里面没有登录信息且重新使用苹果授权登录(Sign in with Apple)会报未知错误
         ASAuthorizationPasswordRequest* authPasswordRequest = [[[ASAuthorizationPasswordProvider alloc] init] createRequest];
         
         NSMutableArray <ASAuthorizationRequest*> * array = [NSMutableArray arrayWithCapacity:2];
         if(authAppleIDRequest) [array addObject:authAppleIDRequest];
         if(authPasswordRequest) [array addObject:authPasswordRequest];
         
         NSArray <ASAuthorizationRequest*> * requests = [array copy];
         ASAuthorizationController* authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:requests];
         */
        authAppleIDRequest.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
        
        //由ASAuthorizationAppleIDProvider创建的授权请求 管理授权请求的控制器
        ASAuthorizationController* authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[authAppleIDRequest]];
        //设置授权控制器通知授权请求的成功与失败的代理
        authorizationController.delegate = self;
        //设置提供 展示上下文的代理,在这个上下文中 系统可以展示授权界面给用户
        authorizationController.presentationContextProvider = self;
        //在控制器初始化期间启动授权流
        [authorizationController performRequests];
        
    } 

プロキシコールバックASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding

//授权成功
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0))
{
    
    
    NSString *userID = nil;
    NSString *userName = nil;
    NSString *userEmail = nil;
    
    EVAppleLoginCredentialModel *model = [[EVAppleLoginCredentialModel alloc] init];
    
    if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
    
    
        
        ASAuthorizationAppleIDCredential *credential = authorization.credential;
        
        //苹果用户唯一标识符,该值在同一个开发者账号下的所有App下是一样的,开发者可以用该唯一标识符与自己后台系统的账号体系绑定起来。
        userID = credential.user;
    
        //苹果用户信息 如果授权过,无法再次获取该信息
        userEmail = credential.email;
        NSPersonNameComponents *fullName = credential.fullName;
        userName = [NSString stringWithFormat:@"%@%@", fullName.familyName, fullName.givenName];
        
        //用于判断当前登录的苹果账号是否是一个真实用户,取值有:unsupported、unknown、likelyReal
        ASUserDetectionStatus realUserStatus = credential.realUserStatus;

        //服务器验证需要使用的参数
        NSString *authorizationCode = [[NSString alloc] initWithData:credential.authorizationCode encoding:NSUTF8StringEncoding];
        NSString *identityToken = [[NSString alloc] initWithData:credential.identityToken encoding:NSUTF8StringEncoding];
        
        NSLog(@"authorization [ASAuthorizationAppleIDCredential] successfully");
        NSLog(@"authorization userID: %@", userID);
        NSLog(@"authorization userName: %@", userName);
        NSLog(@"authorization userEmail: %@", userEmail);
        NSLog(@"authorization realUserStatus: %@", @(realUserStatus));
        NSLog(@"authorization authorizationCode: %@", authorizationCode);
        NSLog(@"authorization identityToken: %@", identityToken);
        
    } else if ([authorization.credential isKindOfClass:[ASPasswordCredential class]]) {
    
    
        //用户登录使用现有的密码凭证
        ASPasswordCredential *passwordCredential = authorization.credential;

        //密码凭证对象的用户标识 用户的唯一标识和密码
        userID = passwordCredential.user;
        NSString *password = passwordCredential.password;
    
        NSLog(@"authorization [ASPasswordCredential] successfully");
        NSLog(@"authorization userID: %@", userID);
        NSLog(@"authorization password: %@", password);
        
        model.user = passwordCredential.user;
        
        userName = @"";
        userEmail = @"";
        
    } else {
    
    
        assert(0);
    }
    
    //数据校验通过后,将这些数据发送给服务器进行验证,等待服务器的回应
    //如果用户选择隐藏邮箱的,email获取不到,其他数据正常,服务端匹配标准userID
    if (![ZJUtils isEmpty:userID]) {
    
    

        //在授权成功的回调中拿到服务器所需要的参数传给后台
        //至此我们所需要做的已经完成了,看后台的验证就行了
        if (self.appleLoginBlock) {
    
    
            self.appleLoginBlock(0, @"苹果授权成功", model);
        }
        
    } else {
    
    
        //授权数据异常
        if (self.appleLoginBlock) {
    
    
            self.appleLoginBlock(-1, @"苹果授权失败", nil);
        }
    }
}

//授权失败
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0))
{
    
    
    NSString *errorMsg = nil;
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    switch (error.code) {
    
    
        case ASAuthorizationErrorCanceled:
            errorMsg = @"用户取消了授权请求";
            break;
        case ASAuthorizationErrorFailed:
            errorMsg = @"授权请求失败";
            break;
        case ASAuthorizationErrorInvalidResponse:
            errorMsg = @"授权请求响应无效";
            break;
        case ASAuthorizationErrorNotHandled:
            errorMsg = @"未能处理授权请求";
            break;
        case ASAuthorizationErrorUnknown:
            errorMsg = @"授权请求失败未知原因";
            break;
    }
    NSLog(@"苹果授权状态:%@", errorMsg);
}

#pragma mark ASAuthorizationControllerPresentationContextProviding
- (ASPresentationAnchor) presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller API_AVAILABLE(ios(13.0))
{
    
    
    return self.view.window;
}

- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorizationコールバックでは、authorizationCode検証としてパラメーターを取得します。

postman を開いてテストしてみましょう:

https://appleid.apple.com/auth/token?client_id=xxx&client_secret=xxx&code=xxx&grant_type=authorization_code&redirect_uri=https://appleid.apple.com

ここに画像の説明を挿入

この時点で、基本的には完了です。実際、Apple ログインの作業のほとんどは、生成などを含め、バックグラウンドで行われます。クライアントは、Apple によってclient_secret承認されたデータをバックエンドに取得するだけでよく、バックエンドはそれを行います。検証。

参考:Apple でサインインとは一体何ですか?

おすすめ

転載: blog.csdn.net/SSY_1992/article/details/127976140