SAML を使用したユーザーのログイン

このドキュメントでは、Identity Platform を使用して Security Assertion Markup Language(SAML)2.0 プロバイダでユーザーのログインを行う方法について説明します。

始める前に

  1. Google Cloud アカウントにログインします。Google Cloud を初めて使用する場合は、アカウントを作成して、実際のシナリオでの Google プロダクトのパフォーマンスを評価してください。新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。
  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  3. Google Cloud プロジェクトで課金が有効になっていることを確認します

  4. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  5. Google Cloud プロジェクトで課金が有効になっていることを確認します

  6. Identity Platform を有効にして、クライアント SDK をアプリに追加します。その方法については、クイックスタートをご覧ください。

プロバイダの構成

  1. Google Cloud コンソールで [ID プロバイダ] ページに移動します。
    [ID プロバイダ] ページに移動

  2. [プロバイダを追加] をクリックし、リストから [SAML] を選択します。

  3. 次の詳細情報を入力します。

    1. プロバイダの名前。プロバイダ ID と同じでも、カスタム名でも構いません。カスタム名を入力する場合は、[プロバイダ ID] の横にある [編集] をクリックして ID を指定します(saml. で始める必要があります)。

    2. プロバイダの [エンティティ ID]。

    3. プロバイダの [SAML SSO の URL]。

    4. プロバイダのトークン署名に使用される証明書。必ず開始文字列と終了文字列を含めてください。例:

      -----BEGIN CERTIFICATE-----
      MIICajCCAdOgAwIBAgIBADANBgkqhkiG9w0BAQ0FADBSMQswCQYDVQQGEwJ1czEL
      ...
      LEzc1JwEGQQVDYQCwsQMSBDAF0QAB0w9GikhqkgBNADABIgABIwAgOdACCjaCIIM
      -----END CERTIFICATE-----
      
  4. サービス プロバイダ でアプリの [エンティティ ID] を入力します。これは通常、アプリの URL です。SAML ID プロバイダでは、これはオーディエンスと呼ばれます。

  5. [承認済みドメイン] のリストにアプリを追加します。たとえば、アプリのログイン URL が https://example.com/login の場合、example.com を追加します。

  6. 必要に応じて、アプリのコールバック URL をカスタマイズします。これは一般に、SAML ID プロバイダでは ACS URL(Assertion Consumer Service URL)と呼ばれます。

    デフォルトのコールバック URL を使用すると、SAML レスポンスを検証する複雑さが軽減されます。このフローをカスタマイズする場合は、プロジェクトの Identity Platform コールバック URL が SAML ID プロバイダで構成されていることを確認してください。通常は、https://[PROJECT-ID].firebaseapp.com/__/auth/handler のような形式になります。詳しくは、認証ハンドラのカスタマイズをご覧ください。

  7. [保存] をクリックします。

プロバイダで必須の要素

Identity Platform は、プロバイダからのレスポンスに <saml:Subject> 要素と <saml:NameID> 要素を想定しています。プロバイダを構成するときに、これらの要素の値を定義しない場合、SAML アサーションは失敗します。

署名リクエスト

認証リクエストに署名することで、認証リクエストのセキュリティを強化できます。

リクエストに署名するには、まず inboundSamlConfigs.patch() を呼び出し、idp_config.sign_requesttrue に設定して、ID プロバイダの署名付きリクエストを有効にします。

REST

リクエストのデータを使用する前に、次のように置き換えます。

  • project-id: Google Cloud プロジェクトの ID
  • provider-id: SAML プロバイダ ID

HTTP メソッドと URL:

PATCH https://identitytoolkit.googleapis.com/admin/v2/projects/project-id/inboundSamlConfigs/provider-id?updateMask=idpConfig.signRequest

リクエストの本文(JSON):

{
  "idp_config": {
    "sign_request": true
  }
}

リクエストを送信するには、次のいずれかのオプションを展開します。

 

REST API を使用して署名付きリクエストを有効にする必要があります。Google Cloud コンソールや Google Cloud CLI の使用はサポートされていません。

レスポンスは、SpCertificate の配列を含む InboundSamlConfig オブジェクトです。リクエストの署名を検証できるように、X509 証明書の値を SAML ID プロバイダで構成します。

ユーザーのログイン

ユーザーをログインさせると、クライアント SDK が認証 handshake を処理し、ペイロードに SAML 属性を含む ID トークンを返します。ユーザーがログインして SAML プロバイダから属性を取得するには、次のようにします。

  1. 前のセクションで構成したプロバイダ ID で SAMLAuthProvider インスタンスを作成します。プロバイダ ID の先頭は saml. にする必要があります。

    Web バージョン 9

    import { SAMLAuthProvider } from "firebase/auth";
    
    const provider = new SAMLAuthProvider("saml.myProvider");

    Web バージョン 8

    const provider = new firebase.auth.SAMLAuthProvider('saml.myProvider');
  2. ログインフローを開始します。ポップアップまたはリダイレクトのいずれかを使用できます。

    Web バージョン 9

    import { SAMLAuthProvider } from "firebase/auth";
    
    const provider = new SAMLAuthProvider("saml.myProvider");

    Web バージョン 8

    const provider = new firebase.auth.SAMLAuthProvider('saml.myProvider');

    リダイレクト

    ログインページにリダイレクトするには、signInWithRedirect() を呼び出します。

    Web バージョン 9

    import { getAuth, signInWithRedirect } from "firebase/auth";
    
    const auth = getAuth();
    signInWithRedirect(auth, provider);

    Web バージョン 8

    firebase.auth().signInWithRedirect(provider);

    次に、getRedirectResult() を呼び出して、ユーザーがアプリに戻ったときに結果を取得します。

    Web バージョン 9

    import { getAuth, getRedirectResult, SAMLAuthProvider } from "firebase/auth";
    
    const auth = getAuth();
    getRedirectResult(auth)
      .then((result) => {
        // User is signed in.
        // Provider data available from the result.user.getIdToken()
        // or from result.user.providerData
      })
      .catch((error) => {
        // Handle Errors here.
        const errorCode = error.code;
        const errorMessage = error.message;
        // The email of the user's account used.
        const email = error.customData.email;
        // The AuthCredential type that was used.
        const credential = SAMLAuthProvider.credentialFromError(error);
        // Handle / display error.
        // ...
      });

    Web バージョン 8

    firebase.auth().getRedirectResult()
      .then((result) => {
        // User is signed in.
        // Provider data available in result.additionalUserInfo.profile,
        // or from the user's ID token obtained from result.user.getIdToken()
        // as an object in the firebase.sign_in_attributes custom claim
        // This is also available from result.user.getIdTokenResult()
        // idTokenResult.claims.firebase.sign_in_attributes.
      }).catch((error) => {
        // Handle / display error.
        // ...
      });
  3. firebase.sign_in_attributes クレームを使用して、SAML プロバイダに関連付けられているユーザー属性を ID トークンから取得します。ID トークンをサーバーに送信するときに、Admin SDK を使用して必ず検証してください。

    ID トークンには、ID プロバイダからの SAML アサーションの NameID 属性で指定されている場合にのみ、ユーザーのメールアドレスが含まれます。

    <Subject>
      <NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">test@email.com</NameID>
    </Subject>
    

    これは、Firebase 発行の ID トークンと UserInfo オブジェクトに入力されます。

現在、クライアント SDK からのサービス プロバイダ主導の SAML フローのみがサポートされています。

ユーザー アカウントのリンク

ユーザーが別の方法(メールアドレスとパスワードなど)を使用してすでにアプリにログインしている場合は、linkWithPopup() または linkWithRedirect() を使用して既存のアカウントを SAML プロバイダにリンクできます。たとえば、Google アカウントにリンクできます。

Web バージョン 9

import { getAuth, linkWithPopup, GoogleAuthProvider } from "firebase/auth";
const provider = new GoogleAuthProvider();

const auth = getAuth();
linkWithPopup(auth.currentUser, provider).then((result) => {
  // Accounts successfully linked.
  const credential = GoogleAuthProvider.credentialFromResult(result);
  const user = result.user;
  // ...
}).catch((error) => {
  // Handle Errors here.
  // ...
});

Web バージョン 8

auth.currentUser.linkWithPopup(provider).then((result) => {
  // Accounts successfully linked.
  var credential = result.credential;
  var user = result.user;
  // ...
}).catch((error) => {
  // Handle Errors here.
  // ...
});

次のステップ