Firebase Authenticationの使い方についてざっくりメモしてみる

  •  
 
トビウオ2019年11月5日 - 17:47 に投稿

概要

  • GoogleのFirebaseにおける機能の1つ、「Firebase Authentication」の利用方法についてのメモ書きです
  • この機能を使うと、ユーザー認証機能を簡単に実装することができます
  • 技術についての概要は、公式(Google)から提供されているWebページ字幕付き動画などをご覧ください
  • 一番基本的な「ポップアップで認証画面を表示する」パターンしか使用していませんので、より高度な機能を利用したい場合は、Google Firebaseの公式ドキュメントを参照してください

実際の操作手順

  1. Firebaseでプロジェクトを作成します
  2. Webサイト上でプロジェクトの画面に移り、どの認証(ログイン方法)を追加したいかを選択する画面まで移動します
    • 具体的には、https://console.firebase.google.com/project/<プロジェクト名>/authentication/providersにアクセスします

Authenticationの設定画面

  1. 登録したい認証の種類(X) を選択し、それに対して設定を行います。これにより、当該認証が有効になります
  2. 認証機能を実装したいアプリケーション側で、firebase認証を扱うためのライブラリをインストールします
    • 例えばJavaScriptの場合、npmに「firebase」というそのものズバリなパッケージがありますのでそちらをインストールします。詳細については、公式ドキュメントをご覧ください
  3. アプリケーション側で、認証Xを利用するためのAPIを使用します。これにより、Firebaseによる認証が実装完了します
  4. つまり、Firebase Hostingを使用しないサイトでもFirebase Authenticationが使えます

Google認証の場合

Google認証の設定画面

まず上記のように設定して、Google認証を有効にします。
次に、実際に認証するコードを書きます。

import firebase, { auth } from 'firebase';
import { firebaseConfig } from './config';

// firebaseを利用するための情報。管理上、別ファイルに切り出してしておくことを推奨
const firebaseConfig = {
  apiKey: "<ウェブ API キー>",
  authDomain: "<プロジェクト ID>.firebaseapp.com",
  databaseURL: "https://<プロジェクト ID>.firebaseio.com",
  projectId: "<プロジェクト ID>",
  storageBucket: "<プロジェクト ID>.appspot.com",
  messagingSenderId: "<サーバーキー>",
};

// 認証前の初期化処理
firebase.initializeApp(firebaseConfig);

// 実際の認証処理。
// signInWithPopupメソッドを叩くと、認証用のポップアップ画面が表示される。
// それにGoogleのIDとパスワードを入力すると、コールバックをfirebase側が処理し、
// 認証成功時はPromise型で認証情報を返す
const provider = new auth.GoogleAuthProvider();
auth().signInWithPopup(provider).then((result) => {
  // 認証成功時、credentialプロパティに認証情報が含まれることがある
  const credential = result.credential;
  if (credential !== null) {
    // credentialに対する型推論結果はauth.AuthCredential型。
    // しかしGoogleの場合はOAuthなので、auth.OAuthCredential型に
    // キャストしないと、IDトークン・アクセストークンを取り出せない
    // (OAuthCredential型はAuthCredential型を継承している)
    const idToken = (credential as auth.OAuthCredential).idToken;
    const accessToken = (credential as auth.OAuthCredential).accessToken;
    console.log(idToken);
    console.log(accessToken);
    // ただ認証するだけでなく、IDトークン・アクセストークンが必要な際は、
    // 別途REST APIを叩くなどして利用できる
  }

  // 認証成功時、userプロパティに認証情報が含まれることがある
  const user = result.user;
  if (user !== null) {
    // displayNameはいわば「表示名」(≒ハンドルネーム)。
    // uidは、firebaseにおいてユーザーを一意に識別するためのユニークなID
    const displayName = user.displayName;
    const uid = user.uid;
    console.log(displayName);
    console.log(uid);
  }
}).catch((error) => {
  // エラー発生時は、その詳細が
  const errorCode = error.code;
  const errorMessage = error.message;
  const email = error.email;
  const credential = error.credential;
  console.log(error);
  console.log(errorCode);
  console.log(errorMessage);
  console.log(email);
  console.log(credential);
});

たったこれだけのコードで、添付画像のような認証画面がポップアップし、

Google認証の確認画面

それに答えるだけで認証情報(ユニークなユーザーIDなど)が取得できます。認証情報はCookieに載っていますので、一度ログイン操作を行えば、再度signInWithPopup()を叩いてもポップアップが出ないのは良いですね。

また、上記コードにおけるresult(firebase.auth.AuthCredential型)におけるuserプロパティはfirebase.User型ですが、より詳細なユーザー情報を取得するためにadditionalUserInfoプロパティも用意されています。
additionalUserInfoプロパティはfirebase.auth.AdditionalUserInfo | null | undefined型なので必ず存在するとは言えませんが、存在した場合はadditionalUserInfo.profileプロパティにて

  • 姓と名それぞれの文字列
  • OAuthとしてどこまでのアクセスが許可されているのか
  • ユーザー自体のロケール

などが取得できます(Google認証における例。TypeScript的にはObject | null型)。

Twitter認証の場合

Twitter認証の設定画面

まず上記のように設定して、Twitter認証を有効にします。

FirebaseはGoogleのプロダクトなのでGoogle認証は簡単な設定で済みましたが、TwitterやFacebookやGitHubなど一般的なSSO認証では、API利用のため「キーとシークレットのペア」が要求されます。Twitterではデベロッパー向けのページで申請することになります。

次に、実際に認証するコードを書きます。といっても実は、

const provider = new auth.GoogleAuthProvider();

const provider = new auth.TwitterAuthProvider();

一行書き換えるだけで済みますが。「認証プロバイダー」「認証情報」「ユーザー」などの各種オブジェクトが抽象化されているためできる芸当というわけです。

メール / パスワード認証の場合

とりあえずONにするだけで使えます。TwitterなどのSSO認証と異なり、APIキーなどの設定は不要です。
ただし、認証用コードがSSO認証と多少異なるので注意が必要です。便宜上、以下のコードではasync/awaitを使用しています。

const email = 'aaa@example.com';
const password = 'password';

try {
  // 既にアカウントが登録されているかを調べる
  const providers = await firebase.auth().fetchSignInMethodsForEmail(email);
  if (providers.includes(firebase.auth.EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD)) {
    // 既にアカウントが存在するので、ログイン操作を実施する
    const result = await auth().signInWithEmailAndPassword(email, password);
    return;
  }

  // アカウントが存在しないので、新たに作成する
  const result = await auth().createUserWithEmailAndPassword(email, password);
  return;
} catch (e) {
  showError(e);
}

なお、これだけだとメールアドレスの正当性を証明していないので、まったく出鱈目なメールアドレスでも「認証」が通ってしまいます。
メールアドレスが正しいことを示したい場合は、次のように確認メールを送信します。

// いったんメールアドレス・パスワードでログインし、未認証ならば確認メールを送信する
const currentUser = firebase.auth().currentUser;
if (currentUser !== null && !currentUser.emailVerified) {
  await currentUser.sendEmailVerification({
    url: 'https://example.com/login/',
    handleCodeInApp: false,
  });
}

// 上記における「url」欄のリンクをユーザーが踏むと期待される。
// 踏んだ先のページに対するリクエストが投げられるので、
// その先でリクエストのGETパラメーターのうち「oobCode」をキーとする値(文字列)を取得する。
// それをapplyActionCodeメソッドに渡せば、正常終了時、メールアドレスの確認が完了する
try {
  // ワンタイムコードの確認
  await auth().applyActionCode(oobCode);
  // メールアドレスの確認完了
} catch (e) {
 // applyActionCodeのエラー
  console.error(e)
};

メアドやパスワード変更、メールリンクのみによる認証などといった細かな点については、(自分では試していませんが)参考資料を参照してください。

電話番号認証

参考資料を参照。非常に丁寧に書かれていてとても良いと思いました。

匿名認証

「一時的なログイン」を表現する際に使用できます。Google認証では

const provider = new auth.GoogleAuthProvider();
auth().signInWithPopup(provider).then((result) => {

だったところ、

auth().signInAnonymously().then((result) => {

に置き換えるだけで実装できます。

また、「一時的なログイン」の後、前述のメアド認証・Google認証などを行うことで、
「通常の認証によるアカウント」が「一時的なアカウント」に入力されたデータにアクセスできます。
言い換えれば、(通常・匿名に関わらず)2つのアカウントの紐付けが可能です。詳しくは公式ドキュメントを参照してください。

参考資料

コメントを追加

プレーンテキスト

  • HTMLタグは利用できません。
  • 行と段落は自動的に折り返されます。
  • ウェブページのアドレスとメールアドレスは自動的にリンクに変換されます。
CAPTCHA
この質問はあなたが人間の訪問者であるかどうかをテストし、自動化されたスパム送信を防ぐためのものです。
画像
Authenticationの設定画面
Google認証の設定画面
Google認証の確認画面
Twitter認証の設定画面