Apple プラットフォームで Yahoo を使用して認証する

Firebase SDK を使用して汎用の OAuth ログインをアプリに統合し、エンドツーエンドのログインフローを実行することで、ユーザーが Firebase での認証に Yahoo などの OAuth プロバイダを使用できます。

始める前に

Yahoo アカウントを使用してユーザーをログインさせるには、まず Firebase プロジェクトのログイン プロバイダとして Yahoo を有効にする必要があります。

  1. Apple プロジェクトに Firebase を追加します
  2. Firebase コンソールで [Auth] セクションを開きます。
  3. [Sign-in method] タブで、[Yahoo!] プロバイダを有効にします。
  4. そのプロバイダのデベロッパー コンソールで取得したクライアント IDクライアント シークレットをプロバイダ構成に追加します。
    1. Yahoo OAuth クライアントを登録するには、Yahoo でのウェブ アプリケーションの登録に関する Yahoo のデベロッパー向けドキュメントの手順を実施してください。

      必ず、OpenID Connect API の 2 つの権限(profileemail)を選択します。

    2. こうしたプロバイダにアプリを登録するときは、必ずプロジェクトの *.firebaseapp.com ドメインをアプリのリダイレクト ドメインとして登録してください。
  5. [保存] をクリックします。

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

Firebase Apple プラットフォーム SDK でログインフローを処理する手順は次のとおりです。

  1. Xcode プロジェクトにカスタム URL スキームを追加します。

    1. プロジェクト構成を開きます(左側のツリービューでプロジェクト名をダブルクリックします)。[TARGETS] セクションでアプリを選択し、[Info] タブを開いて [URL Types] セクションを展開します。
    2. [+] ボタンをクリックし、エンコードされたアプリ ID を URL スキームとして追加します。エンコードされたアプリ ID は、Firebase コンソールの [全般設定] ページで、iOS アプリのセクションで確認できます。その他のフィールドは空白にしておきます。

      完了すると、構成は次のようになります(ただし、値はアプリケーションによって異なります)。

      Xcode のカスタム URL スキーム設定インターフェースのスクリーンショット

  2. プロバイダ ID OAuthProvider を使用して、OAuthProvider のインスタンスを作成します。

    SwiftObjective-C
    var provider = OAuthProvider(providerID: "yahoo.com")
        
    FIROAuthProvider *provider = [FIROAuthProvider providerWithProviderID:@"yahoo.com"];
        
  3. 省略可: OAuth リクエストと一緒に送信したい追加のカスタム OAuth パラメータを指定します。

    SwiftObjective-C
    provider.customParameters = [
    "prompt": "login",
    "language": "fr"
    ]
        
    [provider setCustomParameters:@{@"prompt": @"login", @"language": @"fr"}];
        

    Yahoo がサポートするパラメータについては、Yahoo の OAuth に関するドキュメントをご覧ください。setCustomParameters で Firebase の必須パラメータを渡すことはできません。該当するパラメータは、client_idredirect_uriresponse_typescopestate です。

  4. 省略可: 認証プロバイダにリクエストする、profileemail を超える追加の OAuth 2.0 スコープを指定します。アプリケーションで Yahoo API から限定公開のユーザーデータへのアクセスが必要な場合は、Yahoo のデベロッパー コンソールの [API Permissions] で、Yahoo API に権限をリクエストする必要があります。リクエストされた OAuth スコープは、アプリの API 権限で事前構成されたものと完全一致する必要があります。たとえば、読み取り / 書き込みアクセスがユーザーの連絡先にリクエストされ、それがアプリの API 権限で事前構成されている場合は、読み取り専用の OAuth スコープ sdct-r の代わりに sdct-w を渡す必要があります。そうでなければ、フローは失敗し、エンドユーザーにエラーが表示されます。

    SwiftObjective-C
    // Request access to Yahoo Mail API.
    // Request read/write access to user contacts.
    // This must be preconfigured in the app's API permissions.
    provider.scopes = ["mail-r", "sdct-w"]
        
    // Request access to Yahoo Mail API.
    // Request read/write access to user contacts.
    // This must be preconfigured in the app's API permissions.
    [provider setScopes:@[@"mail-r", @"sdct-w"]];
        

    詳しくは、Yahoo のスコープに関するドキュメントをご覧ください。

  5. 省略可: アプリがユーザーに reCAPTCHA を表示する際の SFSafariViewController または UIWebView の提示方法をカスタマイズするには、AuthUIDelegate プロトコルに従ったカスタムクラスを作成して、そのクラスを credentialWithUIDelegate に渡します。

  6. OAuth プロバイダ オブジェクトを使用して Firebase での認証を行います。

    SwiftObjective-C
    provider.getCredentialWith(nil) { credential, error in
    if error != nil {
    // Handle error.
    }
    if credential != nil {
    Auth().signIn(with: credential) { authResult, error in
      if error != nil {
        // Handle error.
      }
      // User is signed in.
      // IdP data available in authResult.additionalUserInfo.profile.
      // Yahoo OAuth access token can also be retrieved by:
      // (authResult.credential as? OAuthCredential)?.accessToken
      // Yahoo OAuth ID token can be retrieved by calling:
      // (authResult.credential as? OAuthCredential)?.idToken
    }
    }
    }
        
    [provider getCredentialWithUIDelegate:nil
                           completion:^(FIRAuthCredential *_Nullable credential, NSError *_Nullable error) {
    if (error) {
    // Handle error.
    }
    if (credential) {
    [[FIRAuth auth] signInWithCredential:credential
                              completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) {
      if (error) {
        // Handle error.
      }
      // User is signed in.
      // IdP data available in authResult.additionalUserInfo.profile.
      // Yahoo OAuth access token can also be retrieved by:
      // ((FIROAuthCredential *)authResult.credential).accessToken
      // Yahoo OAuth ID token can be retrieved by calling:
      // ((FIROAuthCredential *)authResult.credential).idToken
    }];
    }
    }];
        

    OAuth アクセス トークンを使用して、Yahoo API を呼び出せます。

    たとえば、基本的なプロフィール情報を取得するには、Authorization ヘッダーにアクセス トークンを渡して REST API を呼び出します。

    https://social.yahooapis.com/v1/user/YAHOO_USER_UID/profile?format=json

    YAHOO_USER_UID は、Auth.auth.currentUser.providerData[0].uid フィールドまたは authResult.additionalUserInfo.profile から取得できる Yahoo ユーザーの ID です。

  7. 上記の例ではログインフローを中心に説明していますが、linkWithPopup を使用して Yahoo プロバイダを既存のユーザーにリンクすることもできます。たとえば、複数のプロバイダを同じユーザーにリンクして、どれでもログインを可能にできます。

    SwiftObjective-C
    Auth().currentUser.link(withCredential: credential) { authResult, error in
    if error != nil {
    // Handle error.
    }
    // Yahoo credential is linked to the current user.
    // IdP data available in authResult.additionalUserInfo.profile.
    // Yahoo OAuth access token can also be retrieved by:
    // (authResult.credential as? OAuthCredential)?.accessToken
    // Yahoo OAuth ID token can be retrieved by calling:
    // (authResult.credential as? OAuthCredential)?.idToken
    }
        
    [[FIRAuth auth].currentUser
    linkWithCredential:credential
            completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
    if (error) {
    // Handle error.
    }
    // Yahoo credential is linked to the current user.
    // IdP data available in authResult.additionalUserInfo.profile.
    // Yahoo OAuth access token is can also be retrieved by:
    // ((FIROAuthCredential *)authResult.credential).accessToken
    // Yahoo OAuth ID token can be retrieved by calling:
    // ((FIROAuthCredential *)authResult.credential).idToken
    }];
        
  8. 同じパターンを reauthenticateWithPopup/reauthenticateWithRedirect でも使用できます。これは、ログインしてから短時間のうちに行うべき機密性の高い操作のために、最新の認証情報を取得するのに使われます。

    SwiftObjective-C
    Auth().currentUser.reauthenticateWithCredential(withCredential: credential) { authResult, error in
    if error != nil {
    // Handle error.
    }
    // User is re-authenticated with fresh tokens minted and
    // should be able to perform sensitive operations like account
    // deletion and email or password update.
    // IdP data available in result.additionalUserInfo.profile.
    // Additional OAuth access token is can also be retrieved by:
    // (authResult.credential as? OAuthCredential)?.accessToken
    // Yahoo OAuth ID token can be retrieved by calling:
    // (authResult.credential as? OAuthCredential)?.idToken
    }
        
    [[FIRAuth auth].currentUser
    reauthenticateWithCredential:credential
                      completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
    if (error) {
    // Handle error.
    }
    // User is re-authenticated with fresh tokens minted and
    // should be able to perform sensitive operations like account
    // deletion and email or password update.
    // IdP data available in result.additionalUserInfo.profile.
    // Additional OAuth access token is can also be retrieved by:
    // ((FIROAuthCredential *)authResult.credential).accessToken
    // Yahoo OAuth ID token can be retrieved by calling:
    // ((FIROAuthCredential *)authResult.credential).idToken
    }];
        

Firebase コンソールで [1 つのメールアドレスにつき 1 つのアカウント] 設定を有効にしている場合、Firebase ユーザーが、あるプロバイダ(Google など)用にすでに存在しているメールアドレスを使って別のプロバイダ(Yahoo など)にログインしようとすると、FIRAuthCredential オブジェクト(Yahoo の認証情報)とともにエラー FIRAuthErrorCodeAccountExistsWithDifferentCredential がスローされます。目的のプロバイダにログインするには、まず既存のプロバイダ(Google)にログインしてから、目的のプロバイダの FIRAuthCredential(Yahoo の認証情報)にリンクする必要があります。 これは下記のようになります。

SwiftObjective-C
  // Sign-in with an OAuth credential.
  provider.getCredentialWith(nil) { credential, error in
    // An account with the same email already exists.
    if (error as NSError?)?.code == AuthErrorCode.accountExistsWithDifferentCredential.rawValue {
      // Get pending credential and email of existing account.
      let existingAcctEmail = (error! as NSError).userInfo[AuthErrorUserInfoEmailKey] as! String
      let pendingCred = (error! as NSError).userInfo[AuthErrorUserInfoUpdatedCredentialKey] as! AuthCredential
      // Lookup existing account identifier by the email.
      Auth.auth().fetchProviders(forEmail:existingAcctEmail) { providers, error in
        // Existing email/password account.
        if (providers?.contains(EmailAuthProviderID))! {
          // Existing password account for email. Ask user to provide the password of the
          // existing account.
          // Sign in with existing account.
          Auth.auth().signIn(withEmail:existingAcctEmail, password:password) { user, error in
            // Successfully signed in.
            if user != nil {
              // Link pending credential to account.
              Auth.auth().currentUser?.linkAndRetrieveData(with: pendingCred) { result, error in
                // ...
              }
            }
          }
        }
      }
      return
    }

    // Other errors.
    if error != nil {
      // handle the error.
      return
    }

    // Sign in with the credential.
    if credential != nil {
      Auth.auth().signInAndRetrieveData(with: credential!) { result, error in
        if error != nil {
          // handle the error.
          return
        }
      }
    }
  }

  
  // Sign-in with an OAuth credential.
  [provider getCredentialWithUIDelegate:nil
                             completion:^(FIRAuthCredential *_Nullable credential, NSError *_Nullable error) {
    // An account with the same email already exists.
    if (error.code == FIRAuthErrorCodeAccountExistsWithDifferentCredential) {
      // Get pending credential and email of existing account.
      NSString *existingAcctEmail = error.userInfo[FIRAuthErrorUserInfoEmailKey];
      FIRAuthCredential *pendingCred = error.userInfo[FIRAuthErrorUserInfoUpdatedCredentialKey];
      // Lookup existing account identifier by the email.
      [[FIRAuth auth] fetchProvidersForEmail:existingAcctEmail
                                 completion:^(NSArray<NSString *> *_Nullable providers,
                                              NSError *_Nullable error) {
        // Existing email/password account.
        if ( [providers containsObject:FIREmailAuthProviderID] ) {
          // Existing password account for email. Ask user to provide the password of the
          // existing account.

          // Sign in with existing account.
          [[FIRAuth auth] signInWithEmail:existingAcctEmail
                                 password:password
                               completion:^(FIRUser *user, NSError *error) {
            // Successfully signed in.
            if (user) {
              // Link pending credential to account.
              [[FIRAuth auth].currentUser linkWithCredential:pendingCred
                                                  completion:^(FIRUser *_Nullable user,
                                                               NSError *_Nullable error) {
                // ...
              }];
            }
          }];
        }
      }];
      return;
    }

    // Other errors.
    if (error) {
      // handle the error.
      return;
    }

    // Sign in with the credential.
    if (credential) {
      [[FIRAuth auth] signInAndRetrieveDataWithCredential:credential
          completion:^(FIRAuthDataResult *_Nullable authResult,
                       NSError *_Nullable error) {
        if (error) {
          // handle the error.
          return;
        }
      }];
    }
  }];
  

Firebase でサポートされている他の OAuth プロバイダ(Google、Facebook、Twitter など)では OAuth アクセス トークンに基づいた認証情報を使用して直接ログインできますが、Yahoo などのプロバイダでは Firebase Auth が同様の機能をサポートしていません。これは Yahoo OAuth アクセス トークンの対象デバイスを検証するのに Firebase Auth サーバーを使用できないためです。これは重要なセキュリティ要件です。こうしなければ、アプリケーションやウェブサイトをリプレイ攻撃にさらすことになり、攻撃者があるプロジェクト用に取得した Yahoo OAuth アクセス トークンを使用して別のプロジェクト(被害者)にログインする恐れがあります。代わりに Firebase Auth では、Firebase コンソールで構成した OAuth のクライアント ID とクライアント シークレットを使用して、OAuth フロー全体と認証コード交換を処理する機能を提供しています。認証コードは特定のクライアント ID / シークレットの組み合わせでのみ使用できるため、あるプロジェクトで取得した認証コードを別のプロジェクトで使用することはできません。

このようなプロバイダを、サポートされていない環境で使用する必要がある場合は、サードパーティの OAuth ライブラリと Firebase カスタム認証を使用する必要があります。前者はプロバイダとの認証に、後者はプロバイダの認証情報をカスタム トークンと交換するために必要です。

次のステップ

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

  • アプリでは、User オブジェクトからユーザーの基本的なプロフィール情報を取得できます。ユーザーを管理するをご覧ください。

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

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

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

SwiftObjective-C
let firebaseAuth = Auth.auth()
do {
  try firebaseAuth.signOut()
} catch let signOutError as NSError {
  print("Error signing out: %@", signOutError)
}
NSError *signOutError;
BOOL status = [[FIRAuth auth] signOut:&signOutError];
if (!status) {
  NSLog(@"Error signing out: %@", signOutError);
  return;
}

さまざまな認証エラーに対応できるようにエラー処理コードを追加することもできます。エラーの処理をご覧ください。

Firebase Authentication を使用すると、アプリにエンドツーエンドの ID ソリューションを追加することにより、ユーザー認証、ログイン、オンボーディングをわずか数行のコードで簡単に行えます。

更新日時: Feb 28, 2025

Firebase Authentication を使用すると、アプリにエンドツーエンドの ID ソリューションを追加することにより、ユーザー認証、ログイン、オンボーディングをわずか数行のコードで簡単に行えます。

更新日時: Feb 28, 2025

Firebase Authentication を使用すると、アプリにエンドツーエンドの ID ソリューションを追加することにより、ユーザー認証、ログイン、オンボーディングをわずか数行のコードで簡単に行えます。

更新日時: Feb 28, 2025