Google は、黒人コミュニティのための人種的公平の促進に取り組んでいます。詳細をご覧ください。

AppleとC ++を使用して認証する

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

Firebase SDK を使用してエンド ツー エンドの OAuth 2.0 サインイン フローを実行することにより、ユーザーが Apple ID を使用して Firebase で認証できるようにすることができます。

あなたが始める前に

Apple を使用してユーザーをサインインするには、まず Apple の開発者サイトで Sign In with Apple を構成してから、Firebase プロジェクトのサインイン プロバイダーとして Apple を有効にします。

Apple デベロッパ プログラムに参加する

Sign In with Apple は、 Apple Developer Programのメンバーのみが構成できます。

Apple でサインインを構成する

Firebase プロジェクトで Apple サインインを有効にし、適切に構成する必要があります。構成は、Android および Apple プラットフォームによって異なります。続行する前に、 Apple プラットフォームおよび/またはAndroidガイドの「Apple でサインインを構成する」セクションに従ってください。

Apple をサインイン プロバイダーとして有効にする

  1. Firebase コンソールで、 Authセクションを開きます。 [サインイン方法] タブで、 Appleプロバイダーを有効にします。
  2. Apple サインイン プロバイダーの設定を構成します。
    1. アプリを Apple プラットフォームにのみデプロイする場合は、サービス ID、Apple チーム ID、秘密鍵、および鍵 ID フィールドを空のままにしておくことができます。
    2. Android デバイスでのサポート:
      1. Android プロジェクトに Firebase を追加します。 Firebase コンソールでアプリをセットアップするときは、必ずアプリの SHA-1 署名を登録してください。
      2. Firebase コンソールで、 Authセクションを開きます。 [サインイン方法] タブで、 Appleプロバイダーを有効にします。前のセクションで作成したサービス ID を指定します。また、OAuth コード フロー構成セクションで、Apple チーム ID と、前のセクションで作成した秘密鍵と鍵 ID を指定します。

Apple の匿名データ要件に準拠する

Sign In with Apple では、ユーザーはサインイン時にメール アドレスなどのデータを匿名化するオプションを利用できます。このオプションを選択したユーザーは、ドメインがprivaterelay.appleid.comのメール アドレスを持っています。アプリで Sign In with Apple を使用する場合、これらの匿名化された Apple ID に関して適用される開発者ポリシーまたは Apple の条件に従う必要があります。

これには、直接識別される個人情報を匿名化された Apple ID に関連付ける前に、必要なユーザーの同意を得ることも含まれます。 Firebase Authentication を使用する場合、これには次のアクションが含まれる場合があります。

  • メールアドレスを匿名化された Apple ID に、またはその逆にリンクします。
  • 電話番号を匿名化された Apple ID にリンクする、またはその逆を行う
  • 非匿名のソーシャル認証情報 (Facebook、Google など) を匿名化された Apple ID にリンクするか、その逆を行います。

上記のリストは網羅的なものではありません。アプリが Apple の要件を満たしていることを確認するには、開発者アカウントのメンバーシップ セクションにある Apple Developer Program License Agreement を参照してください。

firebase::auth::Authクラスにアクセスする

Authクラスは、すべての API 呼び出しのゲートウェイです。
  1. Auth および App ヘッダー ファイルを追加します:
    #include "firebase/app.h"
    #include "firebase/auth.h"
    
  2. 初期化コードで、 firebase::Appクラスを作成します。
    #if defined(__ANDROID__)
      firebase::App* app =
          firebase::App::Create(firebase::AppOptions(), my_jni_env, my_activity);
    #else
      firebase::App* app = firebase::App::Create(firebase::AppOptions());
    #endif  // defined(__ANDROID__)
    
  3. firebase::Appfirebase::auth::Authクラスを取得します。 AppAuthの間には 1 対 1 のマッピングがあります。
    firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app);
    

Firebase SDK でログイン フローを処理する

Apple でサインインするプロセスは、Apple と Android のプラットフォームによって異なります。

Apple プラットフォームの場合

C++ コードから呼び出した Apple Sign In Objective-C SDK を介して、Firebase でユーザーを認証します。

  1. サインイン リクエストごとに、ランダムな文字列 (「ナンス」) を生成します。これを使用して、アプリの認証リクエストに応じて取得した ID トークンが付与されたことを確認します。この手順は、リプレイ攻撃を防ぐために重要です。

      - (NSString *)randomNonce:(NSInteger)length {
        NSAssert(length > 0, @"Expected nonce to have positive length");
        NSString *characterSet = @"0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._";
        NSMutableString *result = [NSMutableString string];
        NSInteger remainingLength = length;
    
        while (remainingLength > 0) {
          NSMutableArray *randoms = [NSMutableArray arrayWithCapacity:16];
          for (NSInteger i = 0; i < 16; i++) {
            uint8_t random = 0;
            int errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random);
            NSAssert(errorCode == errSecSuccess, @"Unable to generate nonce: OSStatus %i", errorCode);
    
            [randoms addObject:@(random)];
          }
    
          for (NSNumber *random in randoms) {
            if (remainingLength == 0) {
              break;
            }
    
            if (random.unsignedIntValue < characterSet.length) {
              unichar character = [characterSet characterAtIndex:random.unsignedIntValue];
              [result appendFormat:@"%C", character];
              remainingLength--;
            }
          }
        }
      }
    
    

    サインイン要求で nonce の SHA256 ハッシュを送信すると、Apple はそれを応答で変更せずに渡します。 Firebase は、元のノンスをハッシュし、それを Apple から渡された値と比較することで、応答を検証します。

  2. ノンスの SHA256 ハッシュと、Apple の応答を処理するデリゲート クラスを要求に含めて、Apple のサインイン フローを開始します (次の手順を参照してください)。

      - (void)startSignInWithAppleFlow {
        NSString *nonce = [self randomNonce:32];
        self.currentNonce = nonce;
        ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init];
        ASAuthorizationAppleIDRequest *request = [appleIDProvider createRequest];
        request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
        request.nonce = [self stringBySha256HashingString:nonce];
    
        ASAuthorizationController *authorizationController =
            [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
        authorizationController.delegate = self;
        authorizationController.presentationContextProvider = self;
        [authorizationController performRequests];
      }
    
      - (NSString *)stringBySha256HashingString:(NSString *)input {
        const char *string = [input UTF8String];
        unsigned char result[CC_SHA256_DIGEST_LENGTH];
        CC_SHA256(string, (CC_LONG)strlen(string), result);
    
        NSMutableString *hashed = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
        for (NSInteger i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
          [hashed appendFormat:@"%02x", result[i]];
        }
        return hashed;
      }
    
  3. ASAuthorizationControllerDelegate` の実装で Apple の応答を処理します。サインインが成功した場合は、Apple の応答からの ID トークンとハッシュ化されていないナンスを使用して、Firebase で認証します。

      - (void)authorizationController:(ASAuthorizationController *)controller
         didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)) {
        if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
          ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential;
          NSString *rawNonce = self.currentNonce;
          NSAssert(rawNonce != nil, @"Invalid state: A login callback was received, but no login request was sent.");
    
          if (appleIDCredential.identityToken == nil) {
            NSLog(@"Unable to fetch identity token.");
            return;
          }
    
          NSString *idToken = [[NSString alloc] initWithData:appleIDCredential.identityToken
                                                    encoding:NSUTF8StringEncoding];
          if (idToken == nil) {
            NSLog(@"Unable to serialize id token from data: %@", appleIDCredential.identityToken);
          }
        }
    
  4. 結果のトークン文字列と元の nonce を使用して Firebase Credential を作成し、Firebase にサインインします。

    firebase::auth::OAuthProvider::GetCredential(
            /*provider_id=*/"apple.com", token, nonce,
            /*access_token=*/nullptr);
    
    firebase::Future<firebase::auth::User*> result =
        auth->SignInWithCredential(credential);
    
  5. 同じパターンをReauthenticateで使用できます。これは、最近のログインが必要な機密操作の新しい資格情報を取得するために使用できます。

    firebase::Future<firebase::auth::SignInResult> result =
        user->Reauthenticate(credential);
    
  6. 同じパターンを使用して、アカウントを Apple サインインにリンクできます。ただし、リンクしようとしている Apple アカウントに既存の Firebase アカウントがすでにリンクされている場合は、エラーが発生することがあります。これが発生すると、future はSignInResultのステータスを返し、 kAuthErrorCredentialAlreadyInUseの UserInfo オブジェクトには有効なupdated_credentialが含まれる場合があります。この資格情報は、別の Apple サインイン トークンとナンスを生成する必要なく、 SignInWithCredentialを介して Apple にリンクされたアカウントにサインインするために使用できます。

    updated_credentialSignInResult.UserInfoオブジェクトのメンバーであるため、この操作で資格情報を含めるにはLinkAndRetrieveDataWithCredentialを使用する必要があることに注意してください。

    firebase::Future<firebase::auth::SignInResult> link_result =
        auth->current_user()->LinkAndRetrieveDataWithCredential(credential);
    
    // To keep example simple, wait on the current thread until call completes.
    while (link_result.status() == firebase::kFutureStatusPending) {
      Wait(100);
    }
    
    // Determine the result of the link attempt
    if (link_result.error() == firebase::auth::kAuthErrorNone) {
      // user linked correctly.
    } else if (link_result.error() ==
                   firebase::auth::kAuthErrorCredentialAlreadyInUse &&
               link_result.result()->info.updated_credential.is_valid()) {
      // Sign In with the new credential
      firebase::Future<firebase::auth::User*> result = auth->SignInWithCredential(
          link_result.result()->info.updated_credential);
    } else {
      // Another link error occurred.
    }
    

Android の場合

Android では、Firebase SDK を使用してウェブベースの汎用 OAuth ログインをアプリに統合し、エンド ツー エンドのサインイン フローを実行して、Firebase でユーザーを認証します。

Firebase SDK でサインイン フローを処理するには、次の手順に従います。

  1. Apple に適切なプロバイダー ID で構成されたFederatedOAuthProviderDataのインスタンスを構築します。

    firebase::auth::FederatedOAuthProviderData provider_data("apple.com");
    
  2. オプション:認証プロバイダーから要求するデフォルト以外の追加の OAuth 2.0 スコープを指定します。

    provider_data.scopes.push_back("email");
    provider_data.scopes.push_back("name");
    
  3. オプション: Apple のサインイン画面を英語以外の言語で表示する場合は、 localeパラメーターを設定します。サポートされているロケールについては、 Apple でサインインに関するドキュメントを参照してください。

    // Localize to French.
    provider_data.custom_parameters["language"] = "fr";
    ```
    
  4. プロバイダー データが構成されたら、それを使用して FederatedOAuthProvider を作成します。

    // Construct a FederatedOAuthProvider for use in Auth methods.
    firebase::auth::FederatedOAuthProvider provider(provider_data);
    
  5. Auth プロバイダ オブジェクトを使用して Firebase で認証します。他の FirebaseAuth 操作とは異なり、これは、ユーザーが資格情報を入力できる Web ビューをポップアップ表示することにより、UI を制御することに注意してください。

    サインイン フローを開始するには、 signInWithProviderを呼び出します。

    firebase::Future<firebase::auth::SignInResult> result =
      auth->SignInWithProvider(provider_data);
    

    その後、アプリケーションはFuture でコールバックを待機または登録できます

  6. 同じパターンをReauthenticateWithProviderで使用できます。これを使用して、最近のログインが必要な機密操作の新しい資格情報を取得できます。

    firebase::Future<firebase::auth::SignInResult> result =
      user->ReauthenticateWithProvider(provider_data);
    

    その後、アプリケーションはFuture でコールバックを待機または登録できます

  7. また、 linkWithCredential()を使用して、さまざまな ID プロバイダーを既存のアカウントにリンクできます。

    Apple では、Apple アカウントを他のデータにリンクする前に、ユーザーから明示的な同意を得る必要があることに注意してください。

    たとえば、Facebook アカウントを現在の Firebase アカウントにリンクするには、ユーザーが Facebook にサインインして取得したアクセス トークンを使用します。

    // Initialize a Facebook credential with a Facebook access token.
    AuthCredential credential =
        firebase::auth::FacebookAuthProvider.getCredential(token);
    
    // Assuming the current user is an Apple user linking a Facebook provider.
    firebase::Future<firebase::auth::SignInResult> result =
        auth.getCurrentUser().linkWithCredential(credential);
    

Apple Notes でサインインする

Firebase Auth でサポートされている他のプロバイダーとは異なり、Apple は写真の URL を提供していません。

また、ユーザーが自分の電子メールをアプリと共有しないことを選択した場合、Apple はそのユーザーに固有の電子メール アドレス ( xyz@privaterelay.appleid.comの形式) をプロビジョニングし、それをアプリと共有します。プライベート メール リレー サービスを設定した場合、Apple は匿名化されたアドレスに送信されたメールをユーザーの実際のメール アドレスに転送します。

Apple は、ユーザーが初めてサインインしたときにのみ、表示名などのユーザー情報をアプリと共有します。通常、Firebase は、ユーザーが初めて Apple にサインインしたときに表示名を保存します。これはgetCurrentUser().getDisplayName()で取得できます。ただし、以前に Apple を使用して Firebase を使用せずにユーザーをアプリにサインインさせた場合、Apple は Firebase にユーザーの表示名を提供しません。

次のステップ

ユーザーが初めてサインインすると、新しいユーザー アカウントが作成され、サインインに使用したユーザーの資格情報 (ユーザー名とパスワード、電話番号、または認証プロバイダー情報) にリンクされます。この新しいアカウントは Firebase プロジェクトの一部として保存され、ユーザーのサインイン方法に関係なく、プロジェクト内のすべてのアプリでユーザーを識別するために使用できます。

アプリでは、firebase::auth::user オブジェクトからユーザーの基本的なプロフィール情報を取得できます。ユーザーの管理を参照してください。

Firebase Realtime Database と Cloud Storage セキュリティ ルールでは、ログインしているユーザーの一意のユーザー ID を auth 変数から取得し、それを使用してユーザーがアクセスできるデータを制御できます。