Firebase Authentication with Identity Platform にアップグレードした場合は、OpenID Connect(OIDC)準拠の任意のプロバイダを使用して Firebase でユーザーを認証できます。これにより、Firebase でネイティブにサポートされていない ID プロバイダを使用できるようになります。
始める前に
OIDC プロバイダを使用してユーザーをログインさせるには、まずプロバイダから次のような情報を収集する必要があります。
- クライアント ID: アプリを識別するプロバイダに固有の文字列。プロバイダによっては、サポートするプラットフォームごとに異なるクライアント ID を割り当てている場合があります。これは、プロバイダが発行する ID トークン内の - audクレームの値の一つです。
- クライアント シークレット: プロバイダがクライアント ID の所有権を確認するために使用するシークレット文字列。クライアント ID ごとに、一致するクライアント シークレットが必要です(この値は、認証コードフローを使用する場合にのみ必要です。認証コードフローの使用は強く推奨されています)。 
- 発行元: プロバイダを識別する文字列。この値は、 - /.well-known/openid-configurationが付加される際に、プロバイダの OIDC ディスカバリ ドキュメントがある URL にする必要があります。たとえば、発行元が- https://auth.example.comの場合、ディスカバリ ドキュメントは- https://auth.example.com/.well-known/openid-configurationで入手できる必要があります。
上記の情報を取得したら、Firebase プロジェクトのログイン プロバイダとして OpenID Connect を有効にします。
- Firebase Authentication with Identity Platform にアップグレードしていない場合は、アップグレードしてください。OpenID Connect 認証は、アップグレードされたプロジェクトでのみ使用できます。 
- Firebase コンソールの [ログイン プロバイダ] ページで [新しいプロバイダを追加] をクリックし、続いて [OpenID Connect] をクリックします。 
- 認証コードフローを使用するか、暗黙的な認可フローを使用するかを選択します。 - プロバイダでサポートされているコードフローを常に使用する必要があります。暗黙的フローは安全性が低いため、使用しないことを強くおすすめします。 
- このプロバイダに名前を付けます。生成されたプロバイダ ID(たとえば、 - oidc.example-providerなど)をメモします。この ID は、ログインコードをアプリに追加するときに必要になります。
- クライアント ID とクライアント シークレット、プロバイダの発行元文字列を指定します。これらの値は、プロバイダから割り当てられた値と完全に一致している必要があります。 
- 変更を保存します。 
Firebase SDK を使用したログインフローの処理
OIDC プロバイダを使用して Firebase でユーザーを認証する最も簡単な方法は、Firebase SDK でログインフロー全体を処理することです。
Firebase JavaScript SDK でログインフローを処理する手順は次のとおりです。
- Firebase コンソールで取得したプロバイダ ID を使用して - OAuthProviderのインスタンスを作成します。- Web- import { OAuthProvider } from "firebase/auth"; const provider = new OAuthProvider('oidc.example-provider');- Web- var provider = new firebase.auth.OAuthProvider('oidc.example-provider');
- 省略可: OAuth リクエストと一緒に送信したい追加のカスタム OAuth パラメータを指定します。 - Web- provider.setCustomParameters({ // Target specific email with login hint. login_hint: 'user@example.com' });- Web- provider.setCustomParameters({ // Target specific email with login hint. login_hint: 'user@example.com' });- サポートされているパラメータについては、プロバイダにお問い合わせください。 - setCustomParametersで Firebase の必須パラメータを渡すことはできません。該当するパラメータは- client_id、- response_type、- redirect_uri、- state、- scope、- response_modeです。
- 省略可: 認証プロバイダにリクエストする、基本的なプロフィール以外の追加の OAuth 2.0 スコープを指定します。 - Web- provider.addScope('mail.read'); provider.addScope('calendars.read');- Web- provider.addScope('mail.read'); provider.addScope('calendars.read');- サポートされているスコープについては、プロバイダにお問い合わせください。 
- OAuth プロバイダ オブジェクトを使用して Firebase での認証を行います。 - ユーザーをプロバイダのログインページにリダイレクトするか、ポップアップ ブラウザ ウィンドウでログインページを開きます。 - リダイレクト フロー - signInWithRedirect()を呼び出して、プロバイダのログインページにリダイレクトします。- Web- import { getAuth, signInWithRedirect } from "firebase/auth"; const auth = getAuth(); signInWithRedirect(auth, provider);- Web- firebase.auth().signInWithRedirect(provider);- ユーザーがログインを完了してアプリに戻ったら、 - getRedirectResult()を呼び出してログイン結果を取得できます。- Web- import { getAuth, getRedirectResult, OAuthProvider } from "firebase/auth"; const auth = getAuth(); getRedirectResult(auth) .then((result) => { // User is signed in. // IdP data available in result.additionalUserInfo.profile. // Get the OAuth access token and ID Token const credential = OAuthProvider.credentialFromResult(result); const accessToken = credential.accessToken; const idToken = credential.idToken; }) .catch((error) => { // Handle error. });- Web- firebase.auth().getRedirectResult() .then((result) => { // IdP data available in result.additionalUserInfo.profile. // ... /** @type {firebase.auth.OAuthCredential} */ var credential = result.credential; // OAuth access and id tokens can also be retrieved: var accessToken = credential.accessToken; var idToken = credential.idToken; }) .catch((error) => { // Handle error. });- ポップアップ フロー - Web- import { getAuth, signInWithPopup, OAuthProvider } from "firebase/auth"; const auth = getAuth(); signInWithPopup(auth, provider) .then((result) => { // User is signed in. // IdP data available using getAdditionalUserInfo(result) // Get the OAuth access token and ID Token const credential = OAuthProvider.credentialFromResult(result); const accessToken = credential.accessToken; const idToken = credential.idToken; }) .catch((error) => { // Handle error. });- Web- firebase.auth().signInWithPopup(provider) .then((result) => { // IdP data available in result.additionalUserInfo.profile. // ... /** @type {firebase.auth.OAuthCredential} */ var credential = result.credential; // OAuth access and id tokens can also be retrieved: var accessToken = credential.accessToken; var idToken = credential.idToken; }) .catch((error) => { // Handle error. });
- 上記の例ではログインフローを中心に説明していますが、同じパターンで - linkWithRedirect()と- linkWithPopup()を使用して OIDC プロバイダを既存のユーザーにリンクし、- reauthenticateWithRedirect()と- reauthenticateWithPopup()でユーザーを再認証できます。これは、ログインしてから短時間のうちに行うべき機密性の高い操作のために、最新の認証情報を取得するのに使われます。
手動でログインフローを処理する
OpenID Connect ログインフローをアプリにすでに実装している場合は、ID トークンを直接使用して Firebase で認証できます。
Web
import { getAuth, signInWithCredential, OAuthProvider } from "firebase/auth";
const provider = new OAuthProvider("oidc.example-provider");
const credential = provider.credential({
    idToken: idToken,
});
signInWithCredential(getAuth(), credential)
    .then((result) => {
        // User is signed in.
        // IdP data available in result.additionalUserInfo.profile.
        // Get the OAuth access token and ID Token
        const credential = OAuthProvider.credentialFromResult(result);
        const accessToken = credential.accessToken;
        const idToken = credential.idToken;
    })
    .catch((error) => {
        // Handle error.
    });
Web
const provider = new OAuthProvider("oidc.example-provider");
const credential = provider.credential({
    idToken: idToken,
});
firebase.auth().signInWithCredential(credential)
    .then((result) => {
        // User is signed in.
        // IdP data available in result.additionalUserInfo.profile.
        // Get the OAuth access token and ID Token
        const credential = OAuthProvider.credentialFromResult(result);
        const accessToken = credential.accessToken;
        const idToken = credential.idToken;
    })
    .catch((error) => {
        // Handle error.
    });