Skip to content

ユースケース — 既存ユーザストアの投影

既に users、members、employees、accounts などのテーブルがあり、その形が OP 同梱の oidc_users テーブルと一致しない場合でも、そのテーブルを source of truth のままにできます。OP に必要なのは、subject を解決し、許可された claim を返し、password login を使う場合は store.UserPasswordStore contract 経由で password hash を読める投影です。

ソース: examples/24-byo-userstore

構成

example はストレージを 2 つの責務に分けます。

責務バックエンド
OAuth / OIDC レコード: clients、authorization codes、refresh tokens、grants、sessions、PAR、IAT、RAT、access tokens同梱の op/storeadapter/sql schema
エンドユーザレコード: subject、email、name、locale、password hash、tenant metadataembedder 所有の members table

hybridStore*oidcsql.Store を embed し、Users() だけを上書きします。Go の method promotion により、それ以外の substore は SQL adapter のまま残り、/userinfo、ID Token 組み立て、password login だけがアプリケーション所有の member 投影を読みます。

go
type hybridStore struct {
  *oidcsql.Store
  users store.UserPasswordStore
}

func (h *hybridStore) Users() store.UserStore { return h.users }

login flow も同じ投影を password verification に使います。

go
members := &MemberUserStore{db: db}
storage := &hybridStore{Store: durable, users: members}

flow := op.LoginFlow{
  Primary: op.PrimaryPassword{Store: members},
}

provider, err := op.New(
  op.WithStore(storage),
  op.WithLoginFlow(flow),
  // required options...
)

投影 contract

通常、ユーザストア adapter は次を実装します。

Method役割
FindBySubject(ctx, sub)/userinfo と token 組み立て用に、安定した OIDC subject と claim map を読む。
FindByUsername(ctx, username)email address などの login identifier を、同じ安定 subject に解決する。
ReadPasswordHash(ctx, subject)op.PrimaryPassword 用に PHC encoded password hash を返す。未知ユーザや passwordless user では store.ErrNotFound を返す。

カラム名は自由です。example では member_idemail_addresspassword_phcfull_namelocale_preftenant_idstore.User.Subjectstore.User.Claims へ投影しています。

claim release

store.User.Claims に値を入れても、それだけで全 RP に出るわけではありません。OP は scope と claims request による filtering を引き続き適用します。example は member row から custom tenant claim を読みますが、それを許可する scope がないため demo RP には返りません。

アプリケーション固有 claim を scope 経由で出す場合は Public / Internal スコープ、RP が細かく claim を選ぶ場合は Claims リクエスト を参照してください。

composite が必要なケース

この pattern は Users() substore だけを置き換えます。transactional な OAuth cluster は 1 つの SQL adapter に残るため、storeadapter/composite は不要です。

複数の substore を別 backend に振り分けたい場合、たとえば durable な grants / refresh tokens は SQL に置き、interactions / consumed JTIs は Redis に置く場合は Hot / Cold 分離 を使います。

実行

sh
(cd examples/24-byo-userstore && go run -tags example .)

example は OP を :8080、ペアの RP を :9090 で起動します。demo@example.test / demo でログインすると、RP の /me ページで release された ID Token claim を確認できます。

次に読む