Identity Platform を使用する Firebase Authentication にアップグレードした場合は、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 を有効にします。
Identity Platform を使用する Firebase Authentication にアップグレードしていない場合は、アップグレードしてください。OpenID Connect 認証は、アップグレードされたプロジェクトでのみ使用できます。
Firebase コンソールの [ログイン プロバイダ] ページで [新しいプロバイダを追加] をクリックし、続いて [OpenID Connect] をクリックします。
認証コードフローを使用するか、暗黙的な認可フローを使用するかを選択します。
プロバイダでサポートされているコードフローを常に使用する必要があります。暗黙的フローは安全性が低いため、使用しないことを強くおすすめします。
このプロバイダに名前を付けます。生成されたプロバイダ ID(たとえば、
oidc.example-provider
など)をメモします。この ID は、ログインコードをアプリに追加するときに必要になります。クライアント ID とクライアント シークレット、プロバイダの発行元文字列を指定します。これらの値は、プロバイダから割り当てられた値と完全に一致している必要があります。
変更を保存します。
Firebase SDK を使用したログインフローの処理
OIDC プロバイダを使用して Firebase でユーザーを認証する最も簡単な方法は、Firebase SDK でログインフロー全体を処理することです。
Firebase JavaScript SDK でログインフローを処理する手順は次のとおりです。
Firebase コンソールで取得したプロバイダ ID を使用して
OAuthProvider
のインスタンスを作成します。ウェブ向けのモジュラー API
import { OAuthProvider } from "firebase/auth"; const provider = new OAuthProvider('oidc.example-provider');
ウェブ向けの名前空間付き API
var provider = new firebase.auth.OAuthProvider('oidc.example-provider');
省略可: OAuth リクエストと一緒に送信する追加のカスタム OAuth パラメータを指定します。
ウェブ向けのモジュラー API
provider.setCustomParameters({ // Target specific email with login hint. login_hint: '[email protected]' });
ウェブ向けの名前空間付き API
provider.setCustomParameters({ // Target specific email with login hint. login_hint: '[email protected]' });
サポートされているパラメータについては、プロバイダにお問い合わせください。
setCustomParameters
で Firebase の必須パラメータを渡すことはできません。該当するパラメータはclient_id
、response_type
、redirect_uri
、state
、scope
、response_mode
です。省略可: 認証プロバイダにリクエストする、基本的なプロフィール以外の追加の OAuth 2.0 スコープを指定します。
ウェブ向けのモジュラー API
provider.addScope('mail.read'); provider.addScope('calendars.read');
ウェブ向けの名前空間付き API
provider.addScope('mail.read'); provider.addScope('calendars.read');
サポートされているスコープについては、プロバイダにお問い合わせください。
OAuth プロバイダ オブジェクトを使用して Firebase での認証を行います。
ユーザーをプロバイダのログインページにリダイレクトするか、ポップアップ ブラウザ ウィンドウでログインページを開きます。
リダイレクト フロー
signInWithRedirect()
を呼び出して、プロバイダのログインページにリダイレクトします。ウェブ向けのモジュラー API
import { getAuth, signInWithRedirect } from "firebase/auth"; const auth = getAuth(); signInWithRedirect(auth, provider);
ウェブ向けの名前空間付き API
firebase.auth().signInWithRedirect(provider);
ユーザーがログインを完了してアプリに戻ったら、
getRedirectResult()
を呼び出してログイン結果を取得できます。ウェブ向けのモジュラー API
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. });
ウェブ向けの名前空間付き API
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. });
ポップアップ フロー
ウェブ向けのモジュラー API
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. });
ウェブ向けの名前空間付き API
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 で認証できます。
ウェブ向けのモジュラー API
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.
});
ウェブ向けの名前空間付き API
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.
});