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

JavaScript で Apple を使用して認証する

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

始める前に

ユーザーが Apple を使用してログインできるようにするには、まず Apple のデベロッパー サイトで「Apple でサインイン」を構成してから、Firebase プロジェクトのログイン プロバイダとして Apple を有効にします。

Apple Developer Program に参加する

「Apple でサインイン」は Apple Developer Program のメンバーのみが構成できます。

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

Apple Developer サイトで次の手順を行います。

  1. Web 向けに「Apple でサインイン」を設定するの最初のセクションの説明に従って、ウェブサイトをアプリに関連付けます。プロンプトが表示されたら、次の URL を戻り先 URL として登録します。

    https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler

    Firebase プロジェクト ID は、Firebase コンソールの [設定] ページで確認できます。

    作業が完了したら、新しいサービス ID をメモしておきます。この ID は次のセクションで必要になります。

  2. 「Apple でサインイン」の秘密鍵を作成します。新しい秘密鍵と鍵 ID は、次のセクションで必要になります。
  3. メールリンク ログイン、メールアドレスの確認、アカウントの変更の取り消しなど、ユーザーにメールを送信する Firebase Authentication の機能を使用する場合は、Apple のプライベート メール リレーサービスを構成し、noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com(またはカスタマイズしたメール テンプレート ドメイン)を登録します。これにより Apple は、Firebase Authentication によって送信されたメールを、匿名化された Apple のメールアドレスに転送できます。

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

  1. プロジェクトに Firebase を追加します。
  2. Firebase コンソールで [Authentication] セクションを開きます。[Sign-in method] タブで、[Apple] プロバイダを有効にします。前のセクションで作成したサービス ID を指定します。また、[OAuth コードフローの構成] セクションで、Apple チーム ID、前のセクションで作成した秘密鍵と鍵 ID を指定します。

Apple の匿名化データの要件を遵守する

「Apple でサインイン」には、ユーザーがログイン時に、メールアドレスを含む自分のデータを匿名化できるオプションがあります。このオプションを選択したユーザーは、ドメイン privaterelay.appleid.com のメールアドレスが作成されます。アプリで「Apple でサインイン」を使用する場合は、これらの匿名化された Apple ID に関して、Apple が定めるデベロッパー ポリシーと利用規約を遵守する必要があります。

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

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

上記のリストはすべてを網羅しているわけではありません。アプリが Apple の要件を満たしていることを確認するには、デベロッパー アカウントの [Membership] セクションにある Apple Developer Program License Agreement をご覧ください。

Firebase SDK を使用したログインフローの処理

ウェブアプリをビルドする場合、Apple アカウントを使用して Firebase でユーザーを認証する最も簡単な方法は、Firebase JavaScript SDK でログインフロー全体を処理することです。

Firebase JavaScript SDK でログインフローを処理する手順は次のとおりです。

  1. 対応するプロバイダ ID apple.com を使用して、OAuthProvider のインスタンスを作成します。

    var provider = new firebase.auth.OAuthProvider('apple.com');
  2. 省略可: 認証プロバイダにリクエストする、デフォルトを超える追加の OAuth 2.0 スコープを指定します。

    provider.addScope('email');
    provider.addScope('name');

    デフォルトでは、[1 つのメールアドレスにつき 1 つのアカウント] が有効である場合、Firebase ではメールアドレスと名前のスコープをリクエストします。この設定を [1 つのメールアドレスにつき複数のアカウント] に変更すると、Firebase は Apple にスコープをリクエストしません(指定した場合を除きます)。

  3. 省略可: Apple のログイン画面を英語以外の言語で表示する場合は、locale パラメータを設定します。サポートされる言語 / 地域については、「Apple でサインイン」に関するドキュメントをご覧ください。

    provider.setCustomParameters({
      // Localize the Apple authentication screen in French.
      locale: 'fr'
    });
  4. OAuth プロバイダ オブジェクトを使用して Firebase での認証を行います。ユーザーに Apple アカウントでログインするよう促すために、ポップアップ ウィンドウを表示するか、ログインページにリダイレクトします。モバイル デバイスではリダイレクトすることをおすすめします。

    • ポップアップ ウィンドウでログインを行う場合は、signInWithPopup() を呼び出します。

      firebase
        .auth()
        .signInWithPopup(provider)
        .then((result) => {
          /** @type {firebase.auth.OAuthCredential} */
          var credential = result.credential;
      
          // The signed-in user info.
          var user = result.user;
      
          // You can also get the Apple OAuth Access and ID Tokens.
          var accessToken = credential.accessToken;
          var idToken = credential.idToken;
      
          // ...
        })
        .catch((error) => {
          // Handle Errors here.
          var errorCode = error.code;
          var errorMessage = error.message;
          // The email of the user's account used.
          var email = error.email;
          // The firebase.auth.AuthCredential type that was used.
          var credential = error.credential;
      
          // ...
        });
    • ログインページにリダイレクトしてログインを行う場合は、signInWithRedirect() を呼び出します。

      firebase.auth().signInWithRedirect(provider);

      ユーザーがログインを完了してページに戻ったら、getRedirectResult() を呼び出してログイン結果を取得できます。

      // Result from Redirect auth flow.
      firebase
        .auth()
        .getRedirectResult()
        .then((result) => {
          if (result.credential) {
            /** @type {firebase.auth.OAuthCredential} */
            var credential = result.credential;
      
            // You can get the Apple OAuth Access and ID Tokens.
            var accessToken = credential.accessToken;
            var idToken = credential.idToken;
      
            // ...
          }
          // The signed-in user info.
          var user = result.user;
        })
        .catch((error) => {
          // Handle Errors here.
          var errorCode = error.code;
          var errorMessage = error.message;
          // The email of the user's account used.
          var email = error.email;
          // The firebase.auth.AuthCredential type that was used.
          var credential = error.credential;
      
          // ...
        });

      ここではエラーの検出と対応もできます。エラーコードのリストについては、API リファレンスをご覧ください。

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

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

    Apple が表示名などのユーザー情報をアプリと共有するのは、ユーザーの初回ログイン時のみです。通常、ユーザーが初めて Apple でログインしたときに Firebase で表示名が保存されます。この情報は firebase.auth().currentUser.displayName で取得できます。ただし、以前に Apple を使用してアプリへのユーザーのログインを行った際に Firebase を使用していなかった場合、Apple はユーザーの表示名を Firebase に渡しません。

再認証とアカウントのリンク

同じパターンを reauthenticateWithPopup()reauthenticateWithRedirect() でも使用できます。これらは、ログインしてから短時間のうちに行うべき機密性の高い操作のために、最新の認証情報を取得するのに使用できます。

const provider = new firebase.auth.OAuthProvider('apple.com');

firebase
  .auth()
  .currentUser
  .reauthenticateWithPopup(provider)
  .then((result) => {
    // User is re-authenticated with fresh tokens minted and can perform
    // sensitive operations like account deletion, or updating their email
    // address or password.
    /** @type {firebase.auth.OAuthCredential} */
    var credential = result.credential;

    // The signed-in user info.
    var user = result.user;
     // You can also get the Apple OAuth Access and ID Tokens.
    var accessToken = credential.accessToken;
    var idToken = credential.idToken;

    // ...
  })
  .catch((error) => {
    // Handle Errors here.
    var errorCode = error.code;
    var errorMessage = error.message;
    // The email of the user's account used.
    var email = error.email;
    // The firebase.auth.AuthCredential type that was used.
    var credential = error.credential;

    // ...
  });

また、linkWithPopup()linkWithRedirect() を使用して、複数の ID プロバイダを既存のアカウントにリンクできます。

Apple は、Apple アカウントを他のデータにリンクする前にユーザーから明示的な同意を得ることを要件としています。

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

const provider = new firebase.auth.FacebookAuthProvider();
provider.addScope('user_birthday');

// Assuming the current user is an Apple user linking a Facebook provider.
firebase.auth().currentUser.linkWithPopup(provider)
    .then((result) => {
      // Facebook credential is linked to the current Apple user.
      // Facebook additional data available in result.additionalUserInfo.profile,

      // Additional Facebook OAuth access token can also be retrieved.
      // result.credential.accessToken

      // The user can now sign in to the same account
      // with either Apple or Facebook.
    })
    .catch((error) => {
      // Handle error.
    });

Chrome 拡張機能での Firebase 認証

Chrome 拡張機能アプリを作成する場合は、Chrome 拡張機能 ID を追加する必要があります。

  1. Firebase コンソールでプロジェクトを開きます。
  2. [Authentication] セクションで、[ログイン方法] ページを開きます。
  3. 認可済みドメインのリストに URI を次のように追加します。
    chrome-extension://CHROME_EXTENSION_ID

Chrome 拡張機能では HTTP リダイレクトを使用できないため、Chrome 拡張機能ではポップアップ オペレーション(signInWithPopuplinkWithPopup)のみを使用できます。認証ポップアップはブラウザのアクション ポップアップをキャンセルするため、ブラウザのアクション ポップアップではなくバックグラウンド スクリプトからこれらのメソッドを呼び出す必要があります。

Chrome 拡張機能のマニフェスト ファイルで、https://apis.google.com URL を content_security_policy 許可リストに必ず追加してください。

デフォルトの firebaseapp.com ドメインと同様に、カスタム ドメインも Apple で確認する必要があります。

http://auth.custom.example.com/.well-known/apple-developer-domain-association.txt

高度: Node.js 内で Firebase で認証する

Node.js アプリケーションで Firebase により認証する手順は、次のとおりです。

  1. Apple アカウントでユーザーをログインさせ、ユーザーの Apple ID トークンを取得します。これには複数の方法があります。たとえば、Node.js アプリにブラウザのフロントエンドがある場合は、次のようにします。

    1. バックエンドで、ランダムな文字列(「ナンス」)を生成し、その SHA256 ハッシュを計算します。ナンスとは、バックエンドと Apple の認証サーバー間の 1 回のラウンド トリップを検証するために使用する 1 回限りの値です。

      const crypto = require("crypto");
      const string_decoder = require("string_decoder");
      
      // Generate a new random string for each sign-in
      const generateNonce = function(length) {
        const decoder = new string_decoder.StringDecoder("ascii");
        const buf = Buffer.alloc(length);
        var nonce = "";
        while (nonce.length < length) {
          crypto.randomFillSync(buf);
          nonce = decoder.write(buf);
        }
        return nonce.substr(0, length);
      };
      
      const unhashedNonce = generateNonce(10);
      
      // SHA256-hashed nonce in hex
      const hashedNonceHex = crypto.createHash('sha256')
        .update(unhashedNonce).digest().toString('hex');
    2. ログインページで、「Apple でサインイン」の構成に、ハッシュ計算済みのナンスを指定します。

      <script src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script>
      <div id="appleid-signin" data-color="black" data-border="true" data-type="sign in"></div>
      <script>
          AppleID.auth.init({
              clientId: YOUR_APPLE_CLIENT_ID,
              scope: 'name email',
              redirectURI: URL_TO_YOUR_REDIRECT_HANDLER,  // See the next step.
              state: '[STATE]',  // Optional value that Apple will send back to you
                                 // so you can return users to the same context after
                                 // they sign in.
              nonce: HASHED_NONCE  // The hashed nonce you generated in the previous step.
          });
      </script>
      
    3. POST の認証レスポンス サーバー側から Apple ID トークンを取得します。

      app.post('/redirect', (req, res) => {
        const savedState = req.cookies.__session;
        const code = req.body.code;
        const state = req.body.state;
        const appleIdToken = req.body.id_token;
        if (savedState !== state || !code) {
          res.status(403).send('403: Permission denied');
        } else {
          // Sign in with Firebase using appleIdToken. (See next step).
        }
      });
      

    ウェブページでの「Apple でサインイン」の構成もご覧ください。

  2. ユーザーの Apple ID トークンを取得した後、そのトークンを使用して認証情報オブジェクトを作成してから、その認証情報でユーザーをログインさせます。

    // Build Firebase credential with the Apple ID token.
    const provider = new firebase.auth.OAuthProvider('apple.com');
    const authCredential = provider.credential({
      idToken: appleIdToken,
      rawNonce: unhashedNonce,
    });
    
    // Sign in with credential form the Apple user.
    firebase.auth().signInWithCredential(authCredential)
      .then((result) => {
        // User signed in.
      })
      .catch((error) => {
        // An error occurred. If error.code == 'auth/missing-or-invalid-nonce',
        // make sure you're sending the SHA256-hashed nonce as a hex string
        // with your request to Apple.
        console.log(error);
      });

次のステップ

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

  • アプリでユーザーの認証ステータスを把握するには、Auth オブジェクトにオブザーバーを設定することをおすすめします。これによって、ユーザーの基本的なプロフィール情報を User オブジェクトから取得できます。ユーザーの管理についての記事をご覧ください。

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

既存のユーザー アカウントに認証プロバイダの認証情報をリンクすることで、ユーザーは複数の認証プロバイダを使用してアプリにログインできるようになります。

ユーザーのログアウトを行うには、signOut を呼び出します。

firebase.auth().signOut().then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});