Identity Platform でマルチテナンシー機能を使う
Identity Platform でマルチテナンシー
この記事は Digital Identity技術勉強会 #iddance Advent Calendar 2023 の 5 日目の記事です。
Google Cloud が提供している IDaaS「Identity Platform」のマルチテナンシー機能を使って、テナントごとのログインを実装する方法をご紹介します。
Identity Platform の概要
まずはこの記事でメインで扱う Identity Platform について、クイックにご紹介したいと思います。
Identity Platform は Google Cloud で提供している認証サービスです。モバイルアプリ、Web アプリに認証機能をかんたんに導入できます。Firebase Authentication の上位版という位置付けで、Firebase Authentication の機能に加えて下記の機能も提供しています。
- 多要素認証 (MFA)
- ブロッキング関数を使った認証フローのカスタマイズ
- OpenID Connect (OIDC) プロバイダ、SAML プロバイダのサポート
- Cloud Logging を使ったユーザー アクティビティ ログと監査ログによるモニタリング
- App Check による不正行為の防止
- マルチテナンシー
- エンタープライズサポートと SLA (99.95%)
- 匿名ユーザーの自動クリーンアップ
- HIPPA の適用
- Identity-Aware Proxy (IAP) との統合
Firebase Authencation を知っている(または使っている)方は多いと思いますが、より高度な機能を使いたい場合は Identity Platform にアップグレードが可能です。ユーザーの移行も必要ないほか、クライアント側で使う必要がある SDK も Firebase Authencation で使っている SDK をそのまま使うことができるので、かんたんにアップグレードできます。
マルチテナンシー
マルチテナンシーはテナントごとにログイン方法および設定を分けることができる機能で、主に B to B サービスで活用できます。
例えばテナント A は自社社員の ID 管理基盤を持っており、OIDC Provider の機能を持っているとします。またテナント B も OIDC Provider の機能を持っているとします。これらのテナントがそれぞれのテナント内のユーザーとして SSO するには、それぞれの OIDC Provider ごとに設定を管理し、ログイン先のテナントごとに切り替えられる必要があります。
マルチテナンシーの機能を使うと、サポートされているプロバイダをテナントごとに管理することができます。ログイン時にログイン先のテナント情報を渡すことで、プロバイダ切り替えることができます。
Identity Platform の作成
まずは Identity Platform を使うための準備を行います。Google Cloud プロジェクトは作成済みの前提で進めます。次の URL にアクセスします。
Google Cloud プロジェクト内でまだ API を有効化していない場合は下図の画面が出るので [IDENTITY PLATFORM を有効化] をクリックします。
マルチテナンシーの設定
マルチテナンシーの設定は [設定] メニューの [セキュリティ] タブから設定できます。[テナントを許可] をクリックし、マルチテナンシー機能を有効化します。
テナントの設定
[テナント] メニューを開くと、テナントの追加と設定が行えます。[テナントを追加] をクリックし、1つ目のテナントを追加します。
[名前] は tenant-a
としました。
作成が完了するとテナント ID が払い出されます。
鉛筆マークをクリックすると、テナントで有効化するプロバイダの設定画面が表示されます。今回は Email / Password 方式を有効化します。
Email / Password を有効化するか確認ダイアログが表示されるので、確認し作成します。
ログインするユーザーの登録方法は、ユーザー自身で登録するか管理側から登録するか、2つの方式が用意されています。自分で登録することを制限することももちろん可能です。
今回は予めユーザーを管理画面から作成しておくことにします。
メールアドレスとパスワードを入力するだけで追加できます。
同様の手順で、2つ目のテナントも tenant-b
という名前で作成しておきます。ユーザーはテナント A とテナント B を切り替えていることがわかるよう、異なるメールアドレスのユーザーを作成しておきます。
サンプルアプリの作成とデプロイ
それぞれのテナントで切り替えてログインできるか確認するため、サンプルアプリを作成します。サンプルアプリとしてシンプルな HTML ファイルを作成し、Firebase Hosting を使ってホスティングします。
Firebase Hosting と Identity Platform をそれぞれ同じ Google Cloud プロジェクト内に作成すると、Identity Platform 自体への認証情報やプロジェクトの指定が省略できるので便利です。
まずは HTML ファイルを用意します。公式サンプルとしても提供されているものがありますが、少し複雑な処理も行なっているので必要最低限の処理に留めたサンプルを用意しました。
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Identity Platform Multi-tenant Example</title>
<!-- Firebase と Firebase Auth UI のインポート -->
<script src="/__/firebase/9.22.1/firebase-app-compat.js"></script>
<script src="/__/firebase/9.22.1/firebase-auth-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/ui/6.1.0/firebase-ui-auth.js"></script>
<link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/6.1.0/firebase-ui-auth.css" />
<script src="/__/firebase/init.js"></script>
<script type="text/javascript">
let ui = null;
function initApp() {
ui = new firebaseui.auth.AuthUI(firebase.auth());
firebase.auth().onAuthStateChanged(function(user) {
const container = document.getElementById('login-container');
if (user) {
const message = document.createElement('p');
container.innerHTML = "ステータス : ログイン済み";
container.appendChild(message);
const button = document.createElement('button');
button.innerHTML = "ログアウト";
button.addEventListener('click', () => {
firebase.auth().signOut();
});
container.appendChild(button);
} else {
const message = document.createElement('p');
container.innerHTML = "ステータス : 未ログイン";
container.appendChild(message);
}
});
const searchParams = new URLSearchParams(window.location.search);
const tenantId = searchParams.get("tenant_id");
firebase.auth().tenantId = tenantId;
ui.reset();
ui.start('#firebaseui-auth-container', {
'signInOptions': [firebase.auth.EmailAuthProvider.PROVIDER_ID],
'credentialHelper': 'none',
'signInFlow': 'popup',
'callbacks': {
'signInSuccessWithAuthResult': function(authResult, redirectUrl) {
return false;
}
}
});
}
window.onload = function() {
initApp();
};
</script>
</head>
<body>
<div>
<main>
<div id="login-container"></div>
<div id="firebaseui-auth-container"></div>
</main>
</div>
</body>
</html>
このサンプルではテナントの指定をクエリパラメータでしています。テナントごとに URL が変わるので、アクセスするだけでテナントの指定まで完了しているような振る舞いをイメージしました。
const searchParams = new URLSearchParams(window.location.search);
const tenantId = searchParams.get("tenant_id");
firebase.auth().tenantId = tenantId;
このアプリは firebase deploy
コマンドを実行するだけでホスティングできます。
Firebase プロジェクトが作成されている前提で、HTML ファイルを配置しているディレクトリで下記コマンドを実行します。対話式でプロジェクトの指定や使用するサービスが設定できます。
$ firebase login
$ firebase init
デプロイごとに下記コマンドを実行するとホスティングができます。HTML ファイルなので 1 ~ 2 分程度で完了します。
$ firebase deploy --only hosting
動作確認
動作を確認してみましょう。
https://<Project ID>.web.app/?tenant_id=<Tenant ID>
にアクセスします (<Project ID>
と <Tenant ID>
は自分の環境に合わせて置き換えてください)。
まずはテナント A のログインを試します。tenant_id
パラメータの指定をテナント A の tenant_id
に設定し、テナント A 内に作成したユーザーのメールアドレスとパスワードでログインします。
ログインに成功しました。
なお、ログアウトした状態でテナント B のユーザーでログインしようとすると新規登録フォームになるので、テナント A に存在していないユーザーであることがわかります。
続いて tenant_id
をテナント B に変えて、テナント B に登録したユーザーのメールアドレスでログインしてみます。
ログインに成功しました。
まとめ
今回はマルチテナンシーの機能をかんたんに試すため Email / Password 方式で実装しましたが、OIDC や SAML といったプロバイダも設定することができます。
BtoB サービスにおいてはそういったプロバイダをサポートすることで、各社の ID 基盤を使った SSO が可能になるので利便性が向上すると思います。ぜひ試してみてください。
明日は iamkdada
さんの「OpenID Foundation の SSF、CAEP、RISC の概要と Microsoft Entra ID での実装について」です。お楽しみに!
Discussion