こんにちは、ビザスク開発グループ クライアント開発チームの松下です。
ビザスクでは認証基盤として Auth0 を導入・検証しています。 調査する中で個人的にハマったポイントについて紹介します。
Auth0 Actions とは
Auth0 には Auth0 Actions という機能があります。 Auth0 Actions を利用すると、以下のようなイベントをトリガーにカスタムロジックを実行することができます。
- ユーザ登録直前
- ユーザ登録直後
- ログイン直後
- パスワード変更直後
例えばユーザ登録直前(Pre User Registration)に、Auth0 とは別のシステムのユーザ ID を取得し Auth0 のユーザプロファイルに保存したい場合は、以下の手順で Action を登録します。
1. Action を作成する
Actions > Library > Build Custom
今回はトリガーを「Pre User Registration」、Runtime を「Node 16」で作成します。
ダッシュボード上でカスタムロジックを記述することができるので、以下のようなコードを書いていきます。
const axios = require("axios"); /** * @param {Event} event - Details about registration event. * @param {PreUserRegistrationAPI} api */ exports.onExecutePreUserRegistration = async (event, api) => { // 別システムのユーザ情報を取得 const remoteUser = await axios.get("https://my-api.example.com/users", { params: { email: event.user.email }, }); // 別システムのユーザIDをAuth0側のユーザプロファイルに保存 api.user.setAppMetadata("my-api-user-id", remoteUser.id); };
onExecutePreUserRegistration
の名の通り、ユーザ登録直前に実行したい処理を自由に書くことができます。
ちなみに依存ライブラリ(axios)の追加もダッシュボード上でおこなえます。
完了したら右上の「Deploy」ボタンを押します。
2. Action を Flow に追加する
Action を登録したら、フローの中に組み込む作業を行います。
Actions > Flows > Pre User Registration
右側の Add Action
の Custom
を選択すると先程作成した Action が表示されているので、真ん中のエリアにドラッグ&ドロップします。
最後に右上の Apply
ボタンを押して完了です。
これでユーザが新規登録する直前に、カスタムロジックが実行されるようになります。
Auth0 Management API でユーザを作成する場合の Pre User Registration の挙動
システムによってはユーザ作成ができるのはユーザ自身だけでなく、システム管理者による操作やバッチプログラムから作成することもあります。
そのような場合、通常のアプリケーションとは別に Machine to Machine(以下M2M)アプリケーションを作成し、Auth0 Management API を利用するのがよくあるパターンです。
M2M アプリケーションを作成する
Applications > Applications > Create application
M2Mアプリケーションを作成します。
Authorized API の指定には「Auth0 Management API」を選択し、必要な Permissions を選択します。(サンプルのため全部選択しています)
これで M2M アプリケーションが作成できました。
Applications > Applications > Sample M2M Application
- Domain
- Client ID
- Client Secret
を控えておきます。
Auth0 Management API を Python から利用する
Auth0 SDK for Python を利用します。
pip install auth0-python
以下のようなコードでユーザを作成できます。domain
, client_id
, client_secret
は先程控えておいた値を入れます。
from auth0.v3.authentication import GetToken from auth0.v3.management import Auth0 domain = "****" client_id = "****" client_secret = "****" get_token = GetToken(domain) token = get_token.client_credentials( client_id, client_secret, f"https://{domain}/api/v2/", ) mgmt_api_token = token["access_token"] auth0 = Auth0(domain, mgmt_api_token) # Auth0ユーザ作成 auth0.users.create( { "email": "test@example.com", "email_verified": True, "app_metadata": { "my-api-user-id": 123, }, "connection": "email", } )
登録自体はこれで問題ないのですが、実はこの Python プログラムからユーザを作成するときにも Pre User Registration トリガーが反応します。
Auth0 Actions に実装するカスタムロジックによっては、「ユーザ自身がサイトから登録したときにしか実行したくない」というケースもあるかと思います。言い換えると、「M2Mアプリケーションから作成されたユーザ登録時のカスタムロジックを無視したい」というケースです。
どのアプリケーションからのユーザ登録かトリガー内で判定する
調べたところ、カスタムロジックに以下のような分岐を加えることで実現できるようです。
const axios = require("axios"); /** * @param {Event} event - Details about registration event. * @param {PreUserRegistrationAPI} api */ exports.onExecutePreUserRegistration = async (event, api) => { // 【追加】M2Mアプリケーションからのユーザ登録の場合は以降の処理をおこなわない if (event.client.client_id === "****") { return; } // 別システムのユーザ情報を取得 const remoteUser = await axios.get("https://my-api.example.com/users", { params: { email: event.user.email }, }); // 別システムのユーザIDをAuth0側のユーザプロファイルに保存 api.user.setAppMetadata("my-api-user-id", remoteUser.id); };
****
には先程作成した M2M アプリケーションの client_id
が入ります。
公式ドキュメント によると、引数の event
からは client 以外にもリクエストの詳細が取得できるようです。特定のIPのみアクセス許可する、といった制御もできそうですね。
終わりに
以上、onExecutePreUserRegistration
の意外な挙動の紹介でした。
てっきり Auth0 Actions はユーザ自身が登録するイベントにのみ関係するものだと思いこんでいたのですが、よくよく考えるとユーザ登録の方法なんていくらでも作れますもんね。今回のようなケースがあるので、Auth0 に作成する Application は使い回しをせず、しっかりと用途別に作成するのが良いと感じました。
Auth0 はかなりドキュメントがしっかりしているので、検証作業は結構楽しくやらせてもらっています。引き続き本導入に向けて頑張っていこうと思います 💪