🐶

Identity Platform[GCP]の使い方(ついでにCloud runとの連携も)

2022/03/26に公開

概要

公式以外に使用方法を日本語で説明したものが見当たらなかったので、記述します。

Identity Platform の説明

GCP の IDaaS サービスです。GCP 関連だと Firebase Authrization が基本だと思いますが、その裏で動いているのが Identity Platform です。サービスの違いはとくにありませんが、違いは「マルチテナント機能」です。要するに、ユーザーグループ(≒ テナント)に分けることができます。

基本的な使い方は、Firebase Authrization と同じで、各言語のライブラリも同じものを使用します。Web ブラウザ上で使用する際は「identitytoolkit」を使用し、基本的に Firebase と同じ環境で大丈夫です。

サンプルスニペット

ここでは JavaScript で説明します。ここでは javascript ライブラリの version9 です。

初期化

config の内容は他にもあるので、適宜追加してください。以下は最低限の内容です。このあたりは Firebase ライブラリで必要な処理になるため、詳細は割愛します。

import { initializeApp } from "firebase/app";
const config = {
  apiKey: "~~",
  authDomain: ["localhost", "~~"],
};
initializeApp(config);

ログイン

ここでは関数ぽく書いていますが、関数の中身のみ参考にしてください(関数としてのテストはしていません)。

import {
  getAuth,
  EmailAuthProvider,
  signInWithCredential,
  setPersistence,
  browserLocalPersistence,
  getIdToken,
} from "firebase/auth";

export async function login(email, password) {
  const auth = getAuth();
  auth.tenantId = "~~"; //マルチテナント機能を使用している場合は、テナント毎にこれを変更します。使用していない場合は必要ないです。
  // browserLocalPersistenceを指定していますが、これはsignOut関数を呼び出さない限り、ログイン状態を保持します。
  setPersistence(auth, browserLocalPersistence).then(async () => {
    // 今回はEmail+Passwordでのログイン
    const authCredential = EmailAuthProvider.credential(email, password);
    // 今回はEmail+Passwordでのログイン
    await signInWithCredential(auth, authCredential)
      .then(() => {
        // 正常処理
      })
      .catch(() => {
        // 異常処理
      });
  });
}

ついでに Cloud run との連携も

ここでは、Python でスニペットを示しています。
参考とは少し違いますが、マルチテナントを使用したときのことを以下にコメントで記載しました。以下からわかるように、firebase_admin を使用しているため、こちらの初期化関数の呼び出しが別途必要であることを留意してください。

from typing import Any, Callable
from firebase_admin import auth
from functools import wraps
from flask import request, Response

def jwt_authenticated(func: Callable[..., int]) -> Callable[..., int]:
    @wraps(func)
    def decorated_function(*args: Any, **kwargs: Any) -> Any:
        header = request.headers.get("Authorization", None)
        if header:
            token = header.split(" ")[1]
            try:
                decoded_token = auth.verify_id_token(token)
                # decoded_token["firebase"]["tenant"]から「tenantId」を取得できます。
            except Exception as e:
                return Response(status=403, response=f"Error with authentication: {e}")
        else:
            return Response(status=401)

        request.uid = decoded_token["uid"]
        return func(*args, **kwargs)

    return decorated_function

参考

Discussion