Auth0で独自で生成したUUIDをCustom Claimsとして設定する

Auth0で認証周りを作ってて独自のユーザーIDの定義をどう扱うかを結構なやみました。
Firebase Authの場合はFirebase側でユーザーUIDを生成してくれますが、Auth0の場合は生成してくれない。
まあ、sub クレームの値を使えばいいといえばいいし複数のSocial Provider使われた場合でもAccount Link Extension使えば問題ない気もするけど、やっぱり独自のユーザーIDを発行したほうがいいなと思うこともあるわけです。
ということでどの用に対応するかを頑張ったのでここに残しておきます。
独自のユーザーIDを生成し、app metadataにいれる
auth0にはメタデータを管理する機能があります。
メタデータには2種類存在します。
| user metadata | ユーザー設定などのユーザー属性を保存、ログインしているユーザーによって編集される可能性がある |
| app metadata | ユーザー アクセスに影響を与える可能性のある、権限、Auth0 プラン、外部 ID などの情報を保存、ユーザーはこのデータを編集できない |
今回は独自にユーザーID(つまり外部ID)を発行したいのでapp metadataに生成したUUIDを入れるようにします。
app metadataにどのようにUUIDをいれるのか?
Auth0ではActionsという機能があります。 https://auth0.com/docs/customize/actions
ログインしたなどのイベントに応じてnodejsでスクリプトを実行することができます。
ActionsはカスタムのActionを定義することができます。
npmのモジュールも使うことができます。
今回はこのようのに定義しました。
exports.onExecutePostLogin = async (event, api) => {
const { v4: uuidv4 } = require('uuid');
if (event.authorization) {
const app_uuid = event.user.app_metadata.app_uuid || uuidv4();
if (!event.user.app_metadata.app_uuid) {
api.user.setAppMetadata("app_uuid", app_uuid)
}
}
};
ログイン成功後に、app_uuidを保持していなければapp_uuidをapp_metadataに保存するようになっています。
あとはActionsのChoose flowから先程の作ったカスタムアクションを設定すれば大丈夫です。

クライアント側で参照するためにはカスタムクレームに設定する
独自のUUIDを発行することはできましたが、このままだとクライアント側からデータを参照することは難しいです。
そこでカスタムクレームを使ってIdTokenの中に含めてしまえばクライアント側でもユーザーIDを参照することが簡単にできます。
exports.onExecutePostLogin = async (event, api) => {
const { v4: uuidv4 } = require('uuid');
if (event.authorization) {
const app_uuid = event.user.app_metadata.app_uuid || uuidv4();
if (!event.user.app_metadata.app_uuid) {
api.user.setAppMetadata('app_uuid', app_uuid)
}
api.idToken.setCustomClaim('app_uuid', app_uuid)
}
};
こうすることでクライント側でapp_uuidを取得する事ができます。
// middleware.ts
import {
getSession,
withMiddlewareAuthRequired,
} from '@auth0/nextjs-auth0/edge'
import { NextResponse } from 'next/server'
export default withMiddlewareAuthRequired(async function middleware(req) {
const res = NextResponse.next()
const user = await getSession(req, res)
console.log(user?.user.app_uuid)
return res
})
next13でmiddlewareでapp_uuid参照するサンプルコードです。