オプション一覧
op.New に渡せる公開オプションを、設定対象ごとに分類しました。WithIssuer、WithStore、WithKeyset は常に必須です。WithCookieKeys と WithLoginFlow は authorization_code grant を有効にしている場合に必須で、既定 grant 集合では有効です。それ以外は既定を上書きする任意オプションです。op パッケージの godoc(op/doc.go の「Option groups」)にも、同じオプションがグループ別に載っています。
このページの読み方
オプション名のリンクから詳細ページに進めます。「セクション」列は、そのオプションが影響する discovery 文書やエンドポイントの範囲を示します。「既定」が空欄のオプションは組み込みの初期値を持っておらず、明示的に渡したときだけ機能が有効になります。
最初に読むオプション
オプションは次の 3 層に分かれます。上から順に読んでください。
| 層 | オプション | 参照先 |
|---|---|---|
| まずここから | WithIssuer、WithStore、WithKeyset。authorization_code が有効な間は WithCookieKeys と WithLoginFlow。続いて WithProfile。そのうえで多くの場合、WithStaticClients、WithLogger、WithMountPrefix、WithTrustedProxies、WithUI、WithPrometheus、WithAuditLogger | 必須と条件付き必須、プロファイル / feature / grant、クライアント / 登録、観測 |
| ユースケース別 | 追加する機能に合うセクションを選びます。サインイン、UI、トークン、discovery とエンドポイント、subject 戦略、追加 grant、RAR と Grant Management、JWE、mTLS とプロキシ | 認証 / LoginFlow、UI、トークン、Discovery / エンドポイント、subject 戦略、grant、認可機能、暗号化(JWE)、mTLS / プロキシ / ネットワーク |
| ほとんど不要 | 開発・テスト用の切り替え(WithAllowInsecureOutboundForDev、WithAllowLocalhostIssuerForDev)とテスト用の注入(WithClock)。本番では有効にしません。WithAllowPrivateNetwork は別扱いで、プライベートネットワーク上の RP に届くためのネットワーク到達性の設定であり、本番でも正当に使います | mTLS / プロキシ / ネットワーク、運用方針 |
どのオプションが必要か
このページは、op.New に渡せる公開オプションを並べた一覧です。80 以上のオプションがあるため、目的が決まった状態で表を眺めると目的の項目を探しにくいことがあります。下の判定図で関連する領域を見つけ、表の該当セクションへ進んでください。
- これから新規に OP を立ち上げる → まず
WithIssuer、WithStore、WithKeyset、WithCookieKeys、WithLoginFlowを渡します。後ろの 2 つはauthorization_codegrant が有効な場合に必須で、既定 grant 集合では有効です。詳しくは必須オプション と最小 OP の組み立て。 - FAPI を採用せず OAuth 2.1 の姿勢にしたい → これが既定です。
WithProfileなしの OP はprofile.OAuth21で動き、すべての authorization-code request に PKCE を要求し、それ以外は OIDC Core の既定を保ちます。PKCE を送れない RP のために、WithProfile(profile.OIDCCore)で外せます。FAPI 2.0 には本ライブラリのprofile.FAPI2Baseline(またはprofile.FAPI2MessageSigning、profile.FAPICIBA)を使います。これらのプロファイルは mTLS が明示されていなければ DPoP を既定選択します。プロファイルが必要とする grant が組み込まれていない場合、OP はエンドポイントを勝手に mount せずop.Newが失敗します(profile.FAPICIBAはgrant.CIBAを必要とします)。ユースケース: セキュリティプロファイルの宣言、ユースケース: FAPI 2.0 Baseline、ガイド: FAPI 2.0 入門 を参照。 - プロファイル全体ではなく、機能を 1 つだけ有効にしたい →
WithFeature(feature.PAR)/JAR/JARM/DPoP/MTLS/Introspect/Revoke。public / native client は常に PKCE 必須で、既定のprofile.OAuth21と FAPI プロファイル下ではすべての認可コードクライアントに PKCE が必須です。Dynamic Registration、RAR、Grant Management は追加設定が必要なので、それぞれ専用オプションから有効化します。 /tokenで受け付ける grant の集合を絞りたい →WithGrants(grant.AuthorizationCode, grant.RefreshToken, grant.ClientCredentials, grant.DeviceCode)。協力者(collaborator)を要する grant は専用のオプション(WithCIBAGrant(...)、WithJWTBearerGrant(...))で有効にします。詳しくはgrant を有効にする規則を参照してください。WithCustomGrant(...)とWithTokenExchangeGrant(...)も、それぞれの grant に必要なものをまとめて公開します。- 送信者制約付きのアクセストークンにしたい → DPoP 系:
WithFeature(feature.DPoP)+ 必要に応じてWithDPoPNonceSource(op.NewInMemoryDPoPNonceSource(...))。mTLS 系:WithFeature(feature.MTLS)+ 必要に応じてWithMTLSProxy(op.MTLSProxy{HeaderName: ..., TrustedProxies: ...})。WithMTLSProxyとWithMTLSRootCAsにはfeature.MTLSが必要です。複数レプリカで DPoP nonce を使うなら、op/storeadapter/redisのStore.DPoPNonceSourceを使います。詳しくはガイド: 送信者制約付きトークン、DPoP、mTLS、ユースケース: DPoP nonce フロー。 - アクセストークンを JWT / opaque で切り替えたい → OP 全体の既定は
WithAccessTokenFormat(...)、RFC 8707 リソースごとに分けたいときはWithAccessTokenFormatPerAudience(...)。ガイド: アクセストークンの形式 を参照。 - sector ごとに pairwise
subにしたい →WithPairwiseSubject(salt)(32 byte 以上の salt)。ユースケース: Pairwise subject を参照。 - 起動時にクライアントを静的に投入したい →
WithStaticClients(op.PublicClient{...}, op.ConfidentialClient{...}, op.PrivateKeyJWTClient{...})(構造体リテラル)。ガイド: クライアント種別 を参照。 - Dynamic Client Registration を使いたい →
WithDynamicRegistration(...)。ユースケース: 動的クライアント登録 を参照。 - introspection / revocation エンドポイントを公開したい →
WithFeature(feature.Introspect)および / またはWithFeature(feature.Revoke)。細かな調整は下の「プロファイル / feature / grant」表を参照。 - scope カタログを拡張したい → discovery に出す scope は
WithScope(op.PublicScope("name", "label"))、内部用はWithScope(op.InternalScope("name"))。ガイド: scope と claim、ユースケース: Public / Internal スコープ を参照。 - 独自の
grant_typeを追加したい →WithCustomGrant(handler)。ユースケース: カスタム grant を参照。 - i18n(国際化)対応をしたい →
WithDefaultLocale(...)、WithLocaleBundle(bundle)、WithPreferredLocaleStore(...)。ユースケース: i18n / ロケール解決 を参照。 - JWE request object を復号したい → OP が受け取る JWE の鍵に
WithEncryptionKeyset(...)を指定し、必要ならWithSupportedEncryptionAlgs(op.EncryptionAlgs{KeyManagement: ..., ContentEncryption: ...})で既定の許可リストを狭めます。外向きの JWE 応答は受信側 client の JWKS の鍵で暗号化します。ユースケース: JWE 暗号化 を参照してください。 - SPA クライアント向けに CORS を開けたい →
WithCORSOrigins(...)。ユースケース: SPA 向け CORS を参照。 - Prometheus メトリクスを出したい →
WithPrometheus(registry)。ライブラリは/metricsを公開しないため、ハンドラの公開はルータ側で行います。ユースケース: Prometheus メトリクス を参照。 - 監査ログをアプリログとは別の出力先に流したい →
WithAuditLogger(*slog.Logger)。Audit イベントカタログ を参照。 - ブラウザの SPA にログイン画面を任せたい →
WithUI(op.SPAUI{LoginMount: ...})。WithUI(op.DriverUI{Driver: ...})は、ブラウザ以外のフロントエンドや、HTML 以外を描画する driver 用に取っておきます。op.SPAUIの下ではログイン・同意・アカウント選択を SPA が担い、SPA が<LoginMount>/stateから取得するプロンプトは JSON(interaction.JSONDriver)で描画されます。ユースケース: SPA / 対話画面のカスタマイズ を参照。
オプションの合成
オプションは次の 3 種類のいずれかです。
- 単一値。 引数を取るオプションは、行に加算的と書かれていない限り、1 つの設定を決めます。同じオプションを 2 回渡した場合(
<Name> may be called at most once)や、2 つのオプションが同じ設定を決める場合(WithSubjectGenerator conflicts with prior WithPairwiseSubject)はop.Newが失敗します。後の呼び出しが前の呼び出しを黙って置き換えることはありません。 - 加算的。 繰り返し呼ぶと要素が積み上がります。
WithStaticClients、WithCORSOrigins、WithTrustedProxies、WithTrustedProxyHosts、WithScope、WithFeature、WithProfile、WithInteractions、WithLoginAttemptObserver、WithFirstPartyClients、WithCustomGrant、WithAuthorizationDetailTypes、WithProtectedResourcesが該当します。 - フラグ。 引数のないオプションは冪等で、繰り返しても何も変わりません。
次の 2 つは繰り返し呼べますが、規則がより狭くなります。WithEndpoints は複数回呼べますが、各パスのフィールドは単一値です。WithLocaleBundle のロケールの各キーは単一値で、2 回の呼び出しで同じロケールの別々のキーを渡すことはできますが、同じキーは渡せません。
| オプション | 値 | 内容 | 既定 |
|---|---|---|---|
WithDefaults | ...op.Option | 内側のオプションを既定値として扱う | なし |
WithDefaults:内側の単一値オプションは、WithDefaultsの外にあるオプションが同じ設定を決めたとき、順序に関係なくそちらに譲る。内側の加算的オプションとフラグはそのまま適用される。既定値どうしが同じ設定を決める場合は、やはりop.Newが失敗する。共通のオプション一覧の上に、デプロイごとの上書きを重ねる用途に使う:op.New(op.WithDefaults(baseOptions()...), op.WithAccessTokenTTL(5*time.Minute))。op/testkitは自身の設定をWithDefaults経由で渡すので、testkit.WithOptions(...)は引き続き testkit の既定を置き換える
必須と条件付き必須
| Option | 値 | セクション | 既定 |
|---|---|---|---|
WithIssuer | string | discovery issuer / JWT iss / cookie scope | — |
WithStore | store.Store | プロトコル状態のすべてのサブストア | — |
WithUserStore | store.UserStore | ID トークンと /userinfo の claim を読むエンドユーザ記録の供給元。推論された供給元より優先される | LoginFlow.Primary が op.PrimaryPassword ならその Store(primary の op.StepOneOf 内にあれば最初の op.PrimaryPassword の Store) |
WithKeyset | op.Keyset(既定の ES256 は ECDSA P-256 鍵、WithSigningAlgorithm(op.AlgRS256) を指定したときは 2048 ビット以上の RSA 鍵) | JWKS / JWS 署名 | — |
WithCookieKeys | 32 byte の鍵 | session / CSRF cookie の AES-256-GCM | authorization_code 有効時に必須 |
WithLoginFlow | op.LoginFlow | ユーザのサインイン方法 | authorization_code 有効時に必須 |
WithUserStore:同梱アダプタの具象Users()はそのまま渡せる:op.WithUserStore(st.Users())。有効な grant がエンドユーザを解決しうる(client_credentials以外のすべて)のに、このオプションもop.PrimaryPasswordの store も指定されていないとop.Newが失敗するため、passkey のみ・device-code・CIBA の構成では必須。既定:WithStoreのバックエンドが参照されることはない。client_credentialsだけの OP では不要。
プロファイル / feature / grant
| Option | 値 | セクション | 既定 |
|---|---|---|---|
WithProfile | profile.Profile | 本ライブラリの profile.OAuth21(既定)、profile.OIDCCore、または FAPI プロファイルを宣言 | profile.OAuth21 |
WithFeature | feature.Flag (1 呼び出しで 1 つ、繰り返し可) | PAR / DPoP / mTLS / JAR / JARM / introspect / revoke を個別に有効化 | 控えめな既定 |
WithGrants | ...grant.Type (可変長) | /token で受け付ける grant を限定 | authorization_code、refresh_token |
WithScope | op.Scope (1 呼び出しで 1 つ。op.PublicScope / op.InternalScope コンストラクタを利用) | scope カタログを拡張 | openid、profile、email、address、phone、offline_access |
WithOpenIDScopeOptional | (引数なし) | OAuth 2.0 単独(scope に openid を含まない)を許容 | openid 必須 |
WithStrictOfflineAccess | (引数なし) | refresh_token の発行を offline_access の同意取得時に限定 | 緩やかな既定(openid が付与されれば発行) |
WithProfile:profile.OAuth21は OAuth 2.1 で、すべての authorization-code request に PKCE を求める。profile.OIDCCoreは OpenID Connect Core 1.0 の形で、confidential client では PKCE 任意。他のプロファイルとは組み合わせられず、組み合わせるとop.Newが失敗する。FAPI プロファイルでは mTLS が明示されていない場合に DPoP を既定の送信者制約方式として選択。プロファイルが要求する feature は自動で有効化されるが、grant が足りない場合はop.Newが失敗し、有効化に必要なオプション名をエラーが示す。WithGrants:単一値なので、複数の helper から option を合成する場合は渡す前に grant 集合をまとめてください。既定の集合を置き換えます。WithLoginFlow、WithUI、WithInteractions、WithFirstPartyClientsを明示的に設定したままgrant.AuthorizationCodeを含めないと、op.Newはop.ErrAuthorizationCodeGrantRequiredで失敗します。device_codeや CIBA の claim の取得元になっている login flow と、WithDefaultsの中のオプションは数えません
grant と feature の有効化方法
有効化の仕組みは 3 種類あります。協力者を要しない grant は WithGrants、協力者を要する機能は専用のオプション、プロトコル拡張は WithFeature(またはその機能を要求するプロファイル)で有効にします。WithGrants と専用オプションのどちらからでも有効にできるのは device_code だけです。
| 機能 | 有効化の方法 |
|---|---|
authorization_code、refresh_token | 既定で有効。WithGrants で集合を置き換える |
client_credentials | WithGrants(grant.ClientCredentials) |
| Device code(RFC 8628) | WithDeviceCodeGrant。WithGrants で選んだ集合に、オプションの順序にかかわらず grant.DeviceCode が加わる |
| CIBA poll モード | WithCIBAGrant。これを使わずに WithGrants へ grant.CIBA を入れると op.New が失敗する |
| JWT bearer(RFC 7523) | WithJWTBearerGrant。これを使わずに WithGrants へ grant.JWTBearer を入れると op.New が失敗する |
| Token exchange(RFC 8693) | WithTokenExchangeGrant(WithIDJAGIssuance でもこの grant が有効になる) |
独自の grant_type | WithCustomGrant |
| PAR、JAR、JARM、DPoP、mTLS、introspection、revocation | WithFeature(feature.X)、またはそれを要求するプロファイルによる自動有効化 |
| 動的クライアント登録、RAR、Grant Management | それぞれ専用のオプション(WithDynamicRegistration、WithAuthorizationDetailTypes、WithGrantManagement)。対応する feature フラグはない |
| PKCE | 常にサポート。feature.PKCE は効果がなく、渡すと op.New が起動時に警告を出す。code_challenge は既定(profile.OAuth21)で全クライアントに必須で、confidential client で任意になるのは WithProfile(profile.OIDCCore) の場合だけ |
grant を有効にする規則
- 協力者を要する grant は専用のオプションで有効にします。
WithGrantsだけではop.Newが拒否します。CIBA には login hint の resolver(WithCIBAGrant)が、JWT bearer には信頼する issuer と subject の解決(WithJWTBearerGrant)が必要です。 device_codeは協力者を要しないので、どちらでも有効にできます。WithGrants(..., grant.DeviceCode)でもWithDeviceCodeGrant(op.DeviceCodeGrant{})でも構いません。WithGrantsに挙げた grant を専用のオプションでも有効にしても、何も起きません(no-op)。専用のオプションは、WithGrantsで選んだ集合に、順序にかかわらず自分の grant を加えます。
クライアント / 登録
| Option | 値 | セクション | 既定 |
|---|---|---|---|
WithStaticClients | ...op.ClientSeed (op.PublicClient / op.ConfidentialClient / op.PrivateKeyJWTClient を渡す) | 起動時にクライアントレジストリを初期投入 | 空 |
WithHighEntropyClientSecrets | (引数なし) | OP 全体の client-secret 検証を high-entropy keyed-hash 形式へ切り替える | Argon2 互換の client secret |
WithFirstPartyClients | ...string (client ID) | ファーストパーティ同意スキップの対象 | なし |
WithDynamicRegistration | op.DynamicRegistration | /register を公開(RFC 7591 / 7592) | 無効 |
WithClientIDMetadataDocuments | op.ClientIDMetadataDocuments(構造体。任意の Allow 関数) | Client ID Metadata Documents(draft-ietf-oauth-client-id-metadata-document)を有効にする | 無効 |
WithStaticClients:client_idの重複、SecretもSecretHashもないConfidentialClient、jwksとjwks_uriを両方持つシードはop.Newが拒否する。シードを一度書き込んだ後は、保存済みのレコードが正となる。シードを編集したら起動前にSyncStaticClientsを実行する(クライアントのオンボーディング を参照)WithHighEntropyClientSecrets:既存の Argon2 client hash は後から変換できないため、有効化前に全クライアントを再プロビジョニングするWithClientIDMetadataDocuments:Allow func(ctx, clientID string) boolは、取得の前に毎回呼ばれる。nilなら、ドラフトの URL 規則を満たす URL をすべて許可する。MCP の認可クライアントが使う登録経路で、URL のclient_idは取得したドキュメントに解決される。ドキュメントが宣言できるのはauthorization_codeとrefresh_tokenの grant、認証方式はnoneかprivate_key_jwtだけ。PKCE は常に必須で、これらのクライアントがファーストパーティ自動同意を受けることはない。登録済みのクライアントは、同じ値の URL より優先される。1 回だけ指定できる。Experimental(IETF ドラフトに追従)で、discovery にclient_id_metadata_document_supportedを載せる
認証 / LoginFlow
| Option | 値 | セクション | 既定 |
|---|---|---|---|
WithLoginFlow | op.LoginFlow | Step + Rule の宣言的 DAG | なし |
WithInteractions | ...op.Interaction (可変長) | WithUI で選んだモードが描画する、資格情報以外の追加画面(T&C、KYC など) | consent のみ |
WithLoginAttemptObserver | op.LoginAttemptObserver | RuleAfterFailedAttempts 用の失敗回数集計 | なし |
WithMFAEncryptionKeys | 32 byte の鍵 | TOTP シークレットを AES-256-GCM で保存時暗号化 | なし |
WithAuthnLockoutStore | store.AuthnLockoutStore | 組み込みの password / TOTP / email-OTP / recovery-code ステップが共有する、subject 単位の失敗カウンタを永続化 | WithStore の値が持つ AuthnLockouts() |
WithACRPolicy | op.ACRPolicy (interface)または op.ACRLevels(独自 acr から最小 AAL への map) | ログインがどの acr を満たしたかの判定と報告 | op.DefaultACRPolicy(標準の acr URI のみ) |
WithLoginFlow:LoginFlow.Primaryは subject を確定させる step でなければならない。StepTOTP・StepEmailOTP・StepRecoveryCodeは既知の subject を前提とするため、subject を確定する primary の後にRuleの step として置く。違反するとop.Newが失敗する。Primary(またはそこに置いたStepOneOf)のPrimaryPasskeyはパスワードレスのログインになり、RequireUserVerificationが必須で、未設定ならop.Newが失敗する。独自のop.Authenticatorはop.ExternalStepで組み込み、risk assessor はLoginFlow.Riskに指定するWithInteractions:consentとchooserは組み込み画面の名前で、この名前の要素はop.Newが拒否する
WithAuthnLockoutStore が支えるのは、subject ごとに 1 つの 24 時間ローリングカウンタです。累計 30 回の失敗で 1 時間、90 回で 24 時間ロックします。組み込みの PrimaryPassword、StepTOTP、StepEmailOTP、StepRecoveryCode はすべてこのカウンタに数えられるので、認証要素を切り替えて推測の回数を倍にすることはできません。誤ったパスワードは数えられ、ロック中は正しいパスワードでも誤りと同じ応答で拒否されます。パスワードのログインに成功してもカウンタはリセットされません。存在しないユーザ名と、パスワードハッシュを持たないアカウントはカウンタに触れません。PrimaryPasskey は対象外で、passkey の ceremony の責務です。Primary より後の ExternalStep は CountFailures を設定するとこのカウンタに加わります。Primary では subject が未確定のため設定できず、リモートの verifier が自前のロックアウトを持ちます。ロックが新たに成立すると lockout.engaged を発行します(監査イベント)。
このオプションを指定しない場合、op.New は WithStore の値が AuthnLockouts() を持っていればそれを使います。in-memory、SQL、DynamoDB の adapter は持っており、composite.Store は AuthnLockouts の kind に振り分けたバックエンドのものを転送します。明示したオプションが常に優先されます。カウンタを使うステップ(パスワード、第 2 要素、CountFailures を持つ ExternalStep)がログインフローにあるのに store が解決できないときは、op.New は起動を拒否して op.ErrAuthnLockoutStoreRequired を返します。errors.Is で判定できます。SQL と DynamoDB の store は耐久性があり、レプリカ間で共有されます。inmem.Store.AuthnLockouts() はプロセスローカルで、再起動時にリセットされます。
WithACRPolicy には任意の op.ACRPolicy を渡せます。op.ACRLevels は独自の acr 値を宣言する map 形式です(MFA / ステップアップを参照)。Resolve が ok=false を返したとき、essential の acr 要求は unmet_authentication_requirements で拒否され、voluntary の要求ではログインが到達したレベルの標準 URI が報告されます。
認証 factor のレコードは意図的に store.Store の外にあります。StepTOTP / PrimaryPasskey / StepRecoveryCode / StepEmailOTP はそれぞれ専用 store を受け取ります。登録スキーマ、暗号鍵、アカウント復旧ポリシーは組み込みアプリケーション側の設計だからです。in-memory、SQL、DynamoDB adapter は対応する accessor を公開します。examples/27-durable-mfa-store は、同梱 SQL adapter の factor store を OP のコアテーブルと同じ DB で使う例です。別のバックエンドでだけ factor-store 契約を自前実装してください。
TOTP と email-OTP の Version は store が発行する opaque な equality-only CAS token です。順序性を推測したり自前で生成したりせず、stale な CAS は consumed / stale error として扱います。PasskeyStore.Put は異なる subject の同じ credential ID を atomically に拒否し、credential を別 subject へ移してはなりません。
耐久 store 実装者向けに重要な factor-store 契約が 2 つあります。store.EmailOTPStore.Get は code の ExpiresAt だけでなく EmailOTPRecord.RetainUntil までは record を読める状態に保つ必要があります。これにより、code が失効しても resend cap と brute-force counter はリセットされません。store.RecoveryStore.Consume は、提示された code hash と現在保存されている slot の hash を比較し、古い hash を拒否する必要があります。recovery code を再生成した後に、漏洩済みの古い code が新しい batch の slot を消費するのを防ぐためです。
UI
| Option | 値 | セクション | 既定 |
|---|---|---|---|
WithUI | op.HTMLUI、op.SPAUI、op.DriverUI のうちちょうど 1 つ | サインイン・同意・アカウント選択の描画方式を選ぶ。単一値で、有効なモードは 1 つだけなので組み合わせの問題は生じない | op.HTMLUI{}(組み込みの HTML ページ) |
op.HTMLUI | 構造体: Login / Consent / Chooser(それぞれ op.PageTemplate: Template *html/template.Template と ContentSecurityPolicy) | 組み込みのページを描画し、Template を設定した画面だけを差し替える。state / CSRF / 永続化は OP が担当 | 組み込みのマークアップ |
op.SPAUI | 構造体: LoginMount / StaticDir / ContentSecurityPolicy | SPA の入口と静的アセット一式を OP 側で公開し、interaction の状態も JSON で提供 | なし |
op.DriverUI | 構造体: Driver interaction.Driver | 自前のドライバ(サーバ側レンダラ、外部フロントエンド向けの JSON ドライバなど)で prompt を描画 | なし |
WithLogoutUI | op.LogoutUI (構造体: ConfirmTemplate / SignedOutTemplate (どちらも *html/template.Template で必須)と ContentSecurityPolicy) | RP-Initiated Logout の 2 つのページ(確認ページとサインアウト完了ページ)を組み込み側テンプレートで描画 | 同梱ページ |
WithCORSOrigins | ...string | API CORS に追加する明示 origin | API route は自動導出、ceremony は issuer のみ |
WithDefaultLocale | op.Locale (BCP 47 タグ) | canonical BCP 47 の既定 UI locale。未登録の default は op.New が拒否 | "en" |
WithLocaleBundle | op.LocaleBundle (1 呼び出しで 1 つ、繰り返し可) | 同梱 HTML ドライバ用のロケール別メッセージバンドルを登録 | 英語 + 日本語の初期バンドル |
WithPreferredLocaleStore | op.PreferredLocaleStore | §L.2 優先順序の先頭で参照されるユーザ単位ロケール上書き | なし |
WithUI:ブラウザのサインイン系オプションで、authorization_codeなしで設定するとop.Newが失敗する。各モードは下記op.HTMLUI:Templateが nil の画面は組み込みのマークアップのまま。Loginは同意・チューザ・パスキー以外のすべてのサインイン prompt(パスワード、TOTP、メール OTP、リカバリ、factor 選択、captcha、自前 Step)を担う。カスタムログイン UIを参照op.SPAUI:route になるのはLoginMountだけ。ContentSecurityPolicyは SPA の入口に付く既定のポリシーを置き換える(後述)op.DriverUI:自前のドライバや、独自の translator を持つinteraction.HTMLDriverにページテンプレートを重ねるときは、interaction.TemplateOverlayDriverを渡すWithLogoutUI:確認テンプレートはFieldsを range で出力する必要があり、宣言した CSP は既定のヘッダ全体を置き換え、どのWithUIモードでも有効。ログアウト画面をブランド化するを参照WithCORSOrigins:redirect URI の origin は API CORS 用には自動導出されるが、interaction と end-session の ceremony check は issuer origin + この明示リストだけを許可
WithUI が受け取るモードは 1 つだけなので、モードどうしが衝突することはありません。SPAUI.LoginMount だけが SPA route になります。同意画面とアカウント選択は login interaction state surface を使い、logout の確認ページは通常の end-session flow に残り、サーバが描画します。見た目を変えるには WithLogoutUI を使います。詳細は カスタムアカウント選択 UI を参照してください。
SPA の入口(StaticDir を指定した場合の LoginMount/{uid})には、既定の Content-Security-Policy が付きます。値は default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none' です。インライン script、外部 origin、<base> 要素を使う bundle は SPAUI.ContentSecurityPolicy を指定してください。値は PageTemplate.ContentSecurityPolicy と同じ規則で検証され、拒否された値は op.New が失敗します。アセットの応答にはポリシーが付きません。詳細は SPA カスタムインタラクションを参照してください。
ceremony の origin は issuer と same-site でなければなりません。login.example.com と op.example.com のような issuer の sibling は、ここに列挙すれば利用できますが、完全に別サイトの origin は CORS header を受け取っても interaction / end-session ceremony は動きません。__Host- cookie が SameSite の制約で送信されず、endpoint が 404 を返すためです。UI は issuer 自身か same-site の sibling host に置いてください。cookie 属性は変更できません。
WithLocaleBundle は locale tag を小文字・ハイフン区切りの canonical BCP 47 形式にします。Provider.SetLocaleCookie(w, locale) と Provider.ClearLocaleCookie(w) が公開 cookie seam です。SetLocaleCookie は exact match と language-only fallback を解決し、登録済み locale に一致しなければ op.ErrLocaleNotRegistered を返します。cookie は __Host-oidc_locale、Secure、HttpOnly、SameSite=Lax で、login session とは独立しています。
トークン
| Option | 値 | セクション | 既定 |
|---|---|---|---|
WithAccessTokenFormat | op.AccessTokenFormat (AccessTokenFormatJWT / AccessTokenFormatOpaque) | OP 全体で JWT / opaque を選択 | JWT |
WithAccessTokenFormatPerAudience | map[string]op.AccessTokenFormat (RFC 8707 リソース → 形式) | audience ごとに形式を切り替え | OP 全体の値 |
WithAccessTokenRevocationStrategy | op.AccessTokenRevocationStrategy | 発行済 JWT アクセストークンの失効ポリシー | grant tombstone |
WithAccessTokenTTL | time.Duration | アクセストークンの寿命 | 5 分 |
WithSigningAlgorithm | op.SigningAlgorithm(op.AlgES256 / op.AlgRS256) | OP がすべての JWS の発行に使う単一のアルゴリズム | ES256 |
WithRefreshTokenTTL | time.Duration | 通常のリフレッシュトークンの寿命 | 30 日 |
WithRefreshTokenOfflineTTL | time.Duration | offline_access が付与されたときのリフレッシュトークンの寿命 | 通常のリフレッシュトークンの寿命を継承 |
WithRefreshGracePeriod | time.Duration (0 で無効化、負値は拒否。リフレッシュトークンをローテーションしない FAPI 2.0 profile では op.New がエラーを返す) | ローテーション後の猶予期間 | 60 秒 |
WithDPoPNonceSource | op.DPoPNonceSource (interface) | サーバ供給の DPoP nonce ストア | なし |
WithIDTokenScopeClaims | ...string(scope 名) | 指定した scope が /userinfo で開放する claim を ID Token にも書き込む | 無効 |
WithAccessTokenRevocationStrategy:値はRevocationStrategyGrantTombstone、RevocationStrategyJTIRegistry、RevocationStrategyNone。既定のGrantTombstoneはStore.GrantRevocations()、JTIRegistryはStore.AccessTokens()を必須とし、いずれもop.Newで検査されるWithSigningAlgorithm:アクティブなWithKeysetの鍵の種類(ES256は ECDSA P-256、RS256は 2048 ビット以上の RSA)と、discovery や動的クライアント登録が示す値が決まる。アルゴリズムを切り替える間は、アクティブな鍵より後ろの Keyset エントリに別アルゴリズムの鍵を置けるが、それぞれにNotAfterが必要。profile.FAPI2Baseline、profile.FAPI2MessageSigning、profile.FAPICIBAではAlgRS256が拒否され、それ以外の値はop.Newが失敗する。1 回だけ指定できるWithRefreshTokenOfflineTTL:既定:WithRefreshTokenTTLを継承(ゼロ値で延長しない)。WithDPoPNonceSource:op.NewInMemoryDPoPNonceSourceが同梱実装WithIDTokenScopeClaims:profile、email、address、phone、またはClaimsが空でない登録済みの custom scope を 1 つ以上渡す。対象はauthorization_code、refresh_token、device_code、CIBA の各 grant の ID Token。OIDC Core §5.4 から意図的に外れる。公開 / 内部 scopeを参照
WithInMemoryDPoPNonceLogger は op.New ではなく op.NewInMemoryDPoPNonceSource に渡す補助オプションです。同梱の in-memory nonce source を使う場合だけ指定します。
profile.FAPI2Baseline と profile.FAPI2MessageSigning はリフレッシュトークンをローテーションしない(Security Profile §5.3.2.1(9))ため、設定すべき猶予期間がなく、これらの profile ではこの option を op.New が拒否します。これらの profile 以外では、負でない duration を指定できます。
WithAccessTokenFormat と WithAccessTokenFormatPerAudience が制御するのは、組み込み grant path が発行するアクセストークンです。custom grant の BoundAccessToken は、どちらの option を指定しても常に RFC 9068 JWT として mint されます。custom grant で opaque 値が必要な場合は、handler 自身で mint して AccessToken として返してください。送信者制約付きにしたい場合も、cnf は handler 自身が付与します。
認可コードおよびその refresh chain から発行される JWT アクセストークンには、userinfo_claims という private claim が入ります。値は OIDC claims リクエストの userinfo メンバーで、リクエストになければ {} です。/userinfo はこの claim から返す claim を決めます。リソースサーバは無視してかまいません。この名前は予約済みで、custom grant の extra claims からは設定できません。
Discovery / エンドポイント
| Option | 値 | セクション | 既定 |
|---|---|---|---|
WithEndpoints | op.Endpoints (構造体: 各エンドポイントのパス上書き) | 各エンドポイントのパスを上書き | 仕様の既定 |
WithMountPrefix | string (/ で始める。ルートに置くなら /) | プロトコルエンドポイントに issuer 相対のパス接頭辞を設定。discovery のパスは issuer から別に決まる | /oidc |
WithClaimsSupported | ...string (可変長) | discovery の claims_supported を埋める | 省略 |
WithClaimsParameterDisabled | (引数なし) | claims_parameter_supported を無効にする | 有効 |
WithACRValuesSupported | ...string (可変長) | acr_values_supported を公開 | 空(discovery に出ず、許可リストなし) |
WithDiscoveryMetadata | op.DiscoveryMetadata (型付きの service_documentation / policy / TOS / UI locale / mTLS alias フィールド + Extra map[string]any) | OP が所有しない RFC 8414 / OIDC Discovery メタデータを discovery 文書に追加 | なし |
WithPARTTL | time.Duration | /par が発行する request_uri の寿命を上書き | 60 秒 |
WithJWKSRotationActive | func() bool | ローテーション期間中だけ JWKS の Cache-Control を短期キャッシュに切り替える述語 | 常に長期キャッシュ |
WithClaimsParameterDisabled:malformed JSON は引き続き拒否するが、正しいclaimspayload の投影は抑止して authorize / PAR では無視するWithACRValuesSupported:空でない場合、同じ許可リストを/auth、/par、CIBA の/bc-authorizeでも強制するWithDiscoveryMetadata:UILocalesSupportedは非空時に自動導出された locale list を上書きし、OP 管理フィールドと衝突するExtrakey は拒否(OP 自身が公開するprompt_values_supportedも含む)WithPARTTL:失効判定はブラウザが/authに URI を提示した時点で行い、その後の code 発行では単回使用性だけを強制
subject 戦略
| Option | 値 | セクション | 既定 |
|---|---|---|---|
WithSubjectGenerator | op.SubjectGenerator (interface) | sub claim の導出を上書き。同梱の op/subject.UUIDv7 が既定 | UUIDv7 をそのまま使用 |
WithPairwiseSubject | []byte salt(32 byte 以上) | OIDC Core §8.1 の sector ごと pairwise sub 導出を有効化 | public(UUIDv7) |
WithSubjectGenerator:generator は各 projection で呼ばれ、同じ input に deterministic で surprise I/O を行ってはならないWithPairwiseSubject:途中で戦略を切り替えるとop.Newが拒否する
grant — Device Code / CIBA / カスタム grant / Token Exchange
| Option | 値 | セクション | 既定 |
|---|---|---|---|
WithDeviceCodeGrant | op.DeviceCodeGrant | RFC 8628 device-authorization grant を有効化 | 無効 |
WithCIBAGrant | op.CIBAGrant | CIBA poll mode を有効化。/bc-authorize を公開し CIBA URN を登録。1 回だけ呼べる | 無効 |
WithCustomGrant | op.CustomGrantHandler | 組み込み側が定義する grant_type URN を /token に登録 | なし |
WithTokenExchangeGrant | op.TokenExchangeGrant(構造体。Policy が必須) | RFC 8693 token-exchange grant を有効化 | 無効 |
WithJWTBearerGrant | op.JWTBearerGrant(構造体。Issuers []op.AssertionIssuer、ResolveSubject func(ctx, op.AssertionSubject) (string, error)) | RFC 7523 §2.1 の JWT bearer grant を有効化し、その URN を /token に登録する | 無効 |
WithIDJAGIssuance | op.IDJAGIssuancePolicy(インターフェース。Allow(ctx, op.IDJAGRequest) (*op.IDJAGDecision, error)。nil 不可) | token exchange が requested_token_type=urn:ietf:params:oauth:token-type:id-jag に対し、この OP が発行した ID token を元に署名付きの Identity Assertion JWT Authorization Grant(ID-JAG)を返せるようにする | 無効 |
WithDeviceCodeGrant:/device_authorizationを公開し/tokenに URN を登録。1 回だけ呼べる。フィールド:VerificationURI(デバイス画面に表示する絶対 URL。既定は<issuer>/device)、TTL(新規device_codeレコードのexpires_in寿命。アクセストークン TTL とは独立。既定 10 分)、PollInterval(広告する pollinterval。これより速い poll はslow_down。既定 5 秒)。ゼロ値のフィールドは既定のまま、負の期間はop.Newが拒否する。この grant はエンドユーザを解決するため、op.NewにはWithUserStoreかop.PrimaryPasswordの store も必要WithCIBAGrant:フィールド:HintResolver(必須)、DefaultRequestTTL(既定 600 秒)、MaxRequestTTL(requested_expiryの上限。ゼロなら上限なし)、PollInterval(既定 5 秒)、MaxPollViolations(既定 5)。ゼロ値のフィールドは既定のまま。負の期間、およびMaxRequestTTLを超えるDefaultRequestTTLはop.Newが拒否する。profile.FAPICIBAでは、既定と最大の有効期限を 10 分までに制限するWithCustomGrant:custom name の重複と組み込み grant type との collision は構築時に拒否される。handler はアクセストークンをそのまま返すか、BoundAccessToken要求として返して OP に署名させるWithTokenExchangeGrant:ポリシーがリクエスト単位で受理可否(admission)を判断し、OP の既定値をさらに狭めることもできる。1 回だけ呼べるWithJWTBearerGrant:各AssertionIssuerにはIssuer(OP 自身の issuer は不可、重複不可)、JWKSURI(https)とJWKSのどちらか一方、空でないAllowedClients、Profile(op.AssertionProfileJWT=ゼロ値、または experimental のop.AssertionProfileIDJAG)を設定する。ResolveSubjectは検証済み assertion をローカルの subject に対応づける。プロビジョニングされていないアカウントにはop.ErrUnknownAssertionSubjectを返す。この grant は end user を解決するため、op.NewはWithUserStoreかop.PrimaryPasswordの store も要求する。これを使わずにWithGrantsへgrant.JWTBearerを入れるとop.Newが失敗する。assertion のjtiはすべて一度きりで(store.ConsumedJTIStoreは複数レプリカで共有する)、refresh token も ID token も発行せず、access token は grant レコードに紐づかないためProvider.RevokeSubjectでは失効しない。1 回だけ呼べるWithIDJAGIssuance:audience、scope、resource を制限できるのはポリシーだけで、拒否するにはop.ErrIDJAGUnknownAudienceかop.ErrIDJAGDeniedを返す。WithTokenExchangeGrantなしでも token-exchange grant が有効になる。1 回だけ呼べる。Experimental(IETF ドラフトに追従)
device-code・CIBA・token exchange の各 grant が発行する credential は、記録された grant の配下に置かれます。そのため grant の失効、ユーザ削除、pairwise sub の解決がこれらにも届きます。custom grant は、handler が grant を記録した場合にだけ grant に紐づきます。custom grant 自身の refresh rotation が発行するアクセストークンは常に JWT です。
DeviceCodeGrant.TTL と DeviceCodeGrant.PollInterval は WithAccessTokenTTL から導出されません。アクセストークンを短命にしても、TV / CLI のペアリング手順までユーザがセカンドスクリーンに移る前に失効しないようにするためです。詳細は Device Code、CIBA、カスタム grant、トークン交換。
認可機能 — RAR / Grant Management / Protected Resource Metadata
| オプション | 値 | 説明 | 既定 |
|---|---|---|---|
WithAuthorizationDetailTypes | ...op.AuthorizationDetailType | RFC 9396 Rich Authorization Requests を有効化 | 無効 |
WithGrantManagement | op.GrantManagement{Actions []op.GrantManagementAction; ActionRequired bool} | OAuth 2.0 Grant Management draft を有効化 | 無効 |
WithProtectedResources | ...op.ProtectedResource | 登録した各リソースについて RFC 9728 protected-resource メタデータを /.well-known/oauth-protected-resource とリソース path の接尾辞で公開し、authorization_servers に issuer を載せる | なし |
WithAuthorizationDetailTypes:受理するtypeを validator とともに登録する。authorization_detailsは/auth、/par、/tokenで検証され、grant に永続化され、JWT アクセストークンと introspection に反映され、discovery で公開される。nil のValidateはop.Newで拒否されるWithGrantManagement:grant_management_action/grant_idを処理し、query / revoke エンドポイントを公開し、token 応答にgrant_idを載せ、設定した action 集合を discovery で公開する。Experimental(IETF draft 追跡)。1 回だけ呼べる(2 回目はop.Newが失敗する)WithProtectedResources:ProtectedResource.IntrospectionClientsはその resource を audience とする access token を指定 confidential caller が introspect するための委譲であり、refresh token には適用されない
op.StepUpChallenge(realm, acrValues, maxAge) は op.New のオプションではなく独立したヘルパで、組み込み側のリソースサーバが返す RFC 9470 の WWW-Authenticate: Bearer challenge を組み立てます。OP 自身はこれを発行しません。
詳細は Rich authorization requests、Grant management、Protected resource メタデータ、MFA / ステップアップ。
暗号化(JWE)
| Option | 値 | セクション | 既定 |
|---|---|---|---|
WithEncryptionKeyset | op.EncryptionKeyset (RSA 2048 bit 以上 / EC P-256/384/521 の秘密鍵、use=enc) | OP の inbound 復号用 JWK を公開し、/auth と /par の JWE request object を復号 | なし |
WithSupportedEncryptionAlgs | op.EncryptionAlgs{KeyManagement []string; ContentEncryption []string} | 既定の許可リスト(RSA-OAEP-256 / ECDH-ES{,+A128KW,+A256KW} × A{128,256}GCM)を 狭める だけ | 既定の許可リスト全体 |
WithEncryptionKeyset:outbound JWE 応答は受信側 client の JWKS を使うWithSupportedEncryptionAlgs:広げることはできない。KeyManagementは JWE のalg、ContentEncryptionはencの値で、それぞれ 1 回だけ狭められる
詳細は ユースケース: JWE 暗号化。
mTLS / プロキシ / ネットワーク
| Option | 値 | セクション | 既定 |
|---|---|---|---|
WithMTLSRootCAs | *x509.CertPool | 直接または前送りされた client certificate を OP 自身が検証するための公開 trust pool。nil は拒否 | 未設定(終端側で検証) |
WithMTLSProxy | op.MTLSProxy{HeaderName string; TrustedProxies []string} | edge でヘッダ経由の mTLS を終端 | なし |
WithTrustedProxies | ...string (CIDR。加算的で、繰り返し呼ぶと積み上がる) | 許可した proxy からの X-Forwarded-For / -Proto / -Host を、実クライアントの IP・スキーム・ホストとして解決 | なし |
WithTrustedProxyHosts | ...string (hostname) | trusted proxy CIDR が設定されている場合に、正規の issuer host 以外の X-Forwarded-Host 許可リストを追加 | issuer host のみ |
WithAllowLocalhostRedirectURIs | (引数なし) | http の redirect URI のホストに文字列 localhost を許可する(RFC 8252 のネイティブアプリとローカル開発向け) | リテラル loopback のみ |
WithAllowLocalhostIssuerForDev | (引数なし) | issuer に文字列 localhost を許可する。ローカル開発と passkey の検証向けで、開発専用 | リテラル loopback の IP のみ |
WithAllowPrivateNetwork | ...op.OutboundTarget | ネットワーク到達性: 指定した取得・配送が、プライベートネットワーク(RFC 1918、loopback、link-local、ULA)に届くことを許容する | すべて拒否 |
WithAllowInsecureOutboundForDev | ...op.OutboundTarget | dev / CI fixture 用に plain-HTTP の loopback 宛先を許容する | 拒否 |
WithJWKSHTTPTransport | http.RoundTripper | JAR と private_key_jwt が使う RP 管理 JWKS 取得の transport を差し替える | システム trust の transport |
WithBackchannelLogout | op.BackchannelLogout(構造体: Transport / Timeout / FanOutBudget) | Back-Channel ログアウトの配送設定 | transport は既定、5 秒、30 秒 |
WithMTLSRootCAs:WithMTLSProxyの後ろでtls_client_authのクライアントを認証するなら必須。feature.MTLSなしで指定するとop.Newがエラーを返すWithMTLSProxy:TrustedProxiesから来た request の forwarded certificate が正本。TrustedProxiesが空ならWithTrustedProxiesの CIDR を使い、両方が空ならop.Newが失敗する。feature.MTLSなしで指定するとop.Newがエラーを返す。(*op.Provider).MTLSProxy()が実効値を読み戻すWithTrustedProxies:未設定の間はこれらのヘッダを無視し、最初に届いたリクエストで警告を 1 回出力する(WithLogger未設定ならslog.Default()へ)WithAllowLocalhostRedirectURIs:リテラル127.0.0.1/[::1]は厳格既定のまま。本番でも使えるWithAllowPrivateNetwork:target はop.OutboundJWKS(client JWKS)、op.OutboundJAR(request_uri)、op.OutboundSector(dynamic registration 時のsector_identifier_uri)、op.OutboundClientIDMetadata(Client ID Metadata Document のclient_idURL。httpスキームも許容。機能と同じく Experimental)、op.OutboundBackchannel(backchannel_logout_uriへの配送)、op.OutboundSharedSignals(Shared Signals の push エンドポイント。クラウドメタデータのアドレスは引き続き拒否する。詳細は Shared Signals)。繰り返し呼ぶと積み上がる。引数なしや未知の値はop.Newが失敗するWithAllowInsecureOutboundForDev:受け付ける target はop.OutboundBackchannel(backchannel_logout_uriと配送)とop.OutboundSharedSignals(http://の push エンドポイント)で、それ以外はop.Newが失敗する。issuer が開発用ホスト(loopback の IP リテラル、localhost、RFC 6761 の.localhost/.test/.invalid/.example配下の名前)でない場合、op.Newは拒否するWithJWKSHTTPTransport:接続時の SSRF 判定は維持されるWithBackchannelLogout:Transportが一斉通知のリクエストを運び、Timeoutは RP ごとのリクエストを、FanOutBudgetは RP ごとの timeout とは独立に 1 event 全体を制限する。ゼロ値のフィールドは既定値になる
WithAllowPrivateNetwork は、プライベートネットワーク上(オンプレミス、サービスメッシュ、社内 RP など)の RP に届くためのネットワーク到達性の設定です。本番でも正当に使え、各 target が広げるのは名前を挙げた取得処理だけです。有効にした target ごとに、op.New は広げる対象を示す 1 行を出します。通常は INFO で、オープンな動的クライアント登録か Client ID Metadata Documents も有効な場合は WARN です。WARN になるのは、JWKS、JAR、sector、Client ID Metadata、Back-Channel ログアウトの各 target で、対象の URL を RP が決めるためです。認証されていない呼び出し元が取得や配送の先を内部サービスへ向けられる(SSRF の露出)ことになります。Shared Signals の target は常に INFO です。
target が無効のまま取得や配送が拒否されると、拒否の内容に解除するオプション名が入ります(; pass op.WithAllowPrivateNetwork(op.OutboundJWKS) to admit private-network targets)。RP の JWKS、request_uri、Client ID Metadata Document の取得では、WithLogger に WARN を 1 行(outbound fetch refused by the private-network deny-list)出します。同じ URL については negative cache の有効期間に 1 回までです。sector_identifier_uri は独自の警告ログに、Back-Channel ログアウトと Shared Signals は失敗時の監査レコードに同じ内容を載せます。RP への応答は変わりません。cloud metadata のアドレスはどのオプションでも拒否され、オプション名は入りません。
観測
| Option | 値 | セクション | 既定 |
|---|---|---|---|
WithLogger | *slog.Logger | 構造化された運用ログ(handler は redaction ミドルウェアでラップされる) | 構築時の診断は slog.Default()、リクエスト時の記録は破棄 |
WithAuditLogger | *slog.Logger | OIDC domain business event 専用の監査 sink。HTTP access log ではない | WithLogger を継承 |
WithPrometheus | *prometheus.Registry | 選定した OP counter を呼び出し側 registry に登録(/metrics route、HTTP lifecycle metric、health endpoint は mount しない) | なし |
運用方針
| Option | 値 | セクション | 既定 |
|---|---|---|---|
WithSessionDurabilityPosture | op.SessionDurabilityPosture | Back-Channel Logout の監査ログに方針を注釈付け(SOC 用途)。実行時の制御は変えない | セッションストアから導出 |
WithSharedSignals | (引数なし) | OP を Shared Signals Framework 1.0 の transmitter にする | 無効 |
WithClock | op.Clock | token の有効期限、監査レコードの timestamp、レート制限 window に使う時刻ソース(テスト用に注入) | time.Now |
WithSessionDurabilityPosture:たとえば AOF 永続化を有効にした Redis のように、導出される値を上書きしたいときに宣言する。SessionDurabilityDurableを宣言したのに、セッションストアが永続でないと報告する場合は、op.Newが警告を 1 回出す。既定:store.SessionDurabilityReporterを実装しDurable()が true を返せば durable(SQL と DynamoDB のアダプタが該当)、そうでなければ volatile。WithSharedSignals:受信側は OAuth クライアントで、ssf.readかssf.manageスコープのclient_credentialsトークンを取得し、ストリームを設定して、CAEP / RISC のイベントを push または poll で受け取る。store.SharedSignalsStoreを実装するストア、store.GrantClientListerを実装するGrants()、WithCookieKeysが必要。ssf.で始まるスコープ名は予約済み。push ワーカーはop.NewからProvider.Shutdownまで動く。詳細は Shared Signals
op.New が拒否する構成
必須オプションの欠落以外にも、次の組み合わせは「受け取って無視する」のではなく、op.New が設定エラーとして返します。
| 構成 | 拒否する理由 |
|---|---|
store.Store が返す substore が typed-nil(nil ポインタを持つ interface) | 単純な nil 判定を通り抜け、初回利用時に panic する |
WithLoginFlow の 2 回指定 | 1 つのプロバイダにログインの仕組みは 1 つだけ |
すでに確定した subject を前提とする LoginFlow.Primary | primary の step が動く時点では subject がまだ決まっていない |
consent / chooser という名前の WithInteractions 要素 | 組み込み画面の名前として予約済み |
| 単一値のオプションの 2 回指定、または同じ設定を決める 2 つのオプション(オプションの合成を参照) | 後の呼び出しが前の設定を黙って置き換えてしまう |
WithUI に nil を渡す。Template のないページに ContentSecurityPolicy を指定した HTMLUI。LoginMount が空、または / で始まらない SPAUI、あるいはアクセスできるディレクトリではない StaticDir。Driver が nil の DriverUI、または Inner が nil の interaction.TemplateOverlayDriver。interaction.NormalizeCSP が拒否する ContentSecurityPolicy | 描画できないモード、または OP が送れないポリシー |
WithGrants に grant.AuthorizationCode がないのに WithUI を設定(WithDefaults の外) | WithUI が描画する prompt は authorization code フローのもの。op.New は op.ErrAuthorizationCodeGrantRequired を返す |
2 回目の WithLogoutUI、nil の ConfirmTemplate または SignedOutTemplate、interaction.NormalizeCSP が拒否する ContentSecurityPolicy、Fields の全要素を出力しない確認テンプレート | リクエスト時に失敗するログアウト画面や、OP が送れないポリシーになる |
2 回目の WithIDTokenScopeClaims、引数なし、空の名前・openid・offline_access・未登録の名前、ID Token が予約している claim を Claims に含む custom scope | claim を開放しない scope や、OP が自分で署名する claim と衝突する scope になる |
PreviousSecret と PreviousSecretHash を両方持つ、または PreviousSecretExpiresAt のない ConfidentialClient のシード。WithHighEntropyClientSecrets のもとでの平文の PreviousSecret(Argon2id でハッシュされる)や Argon2id の PreviousSecretHash | 決して受理されない旧シークレットや、high-entropy の検証器が読めないハッシュになる |
組み込み HTML ドライバ上の PrimaryPasskey ステップ(TemplateOverlayDriver を値・ポインタのどちらで渡した場合も含む) | ドライバが script を出力しないため、WebAuthn の ceremony を完了できるユーザがいない。SPAUI か、ceremony を実行するドライバを持つ DriverUI を使う |
既定のポリシーまたは op.ACRLevels が解決できない WithACRValuesSupported の値、空のキー・AAL1〜AAL3 以外の値・誤ったレベルの標準 URI キーを持つ op.ACRLevels | OP が報告できない acr を広告してしまう |
負の CIBAGrant.DefaultRequestTTL / CIBAGrant.PollInterval、profile.FAPICIBA で 10 分を超える CIBA の既定・最大有効期限 | 許容範囲外 |
secret のない ConfidentialClient シード、jwks と jwks_uri を両方持つクライアントレコード | RFC 7591 §2 が両者の併用を禁じており、空の secret ハッシュは空の client_secret を受理してしまう |
必要な grant が有効でない WithProfile | エラーに、その grant を有効にするオプション名が出る |
profile.OIDCCore を他のプロファイルと併せて宣言 | プロファイル要件が明示的にないことを表すので、他と組み合わせると矛盾するか意味を成さない |
WithUserStore も、ログインフローの op.PrimaryPassword の store もないのに、有効な grant がエンドユーザを解決しうる(client_credentials 以外のすべて) | エンドユーザ記録の供給元がない。WithStore のバックエンドがユーザの参照元になることはない |
StepEmailOTP も、Store・Sender・Users が nil または typed-nil なら op.New を失敗させます。どれも最初のリクエストまで待たずに失敗します。
起動時の診断
受理はされるものの、意図した構成とは考えにくいものがあります。op.New は、そのような構成ごとに警告を構築時に 1 回、WithLogger で渡した logger(未指定なら slog.Default())へ出します。
| 構成 | 警告の内容 |
|---|---|
WithLogger も WithAuditLogger も未指定 | リクエスト処理中の運用ログと監査レコードが破棄される |
WithStaticClients のエントリが、OP の有効にしていない grant_types を挙げている。GrantTypes を空にしたシードは authorization_code と refresh_token を受け取るため、どちらかが有効でなければ警告される | その grant のトークンリクエストは unsupported_grant_type で拒否される。メッセージには有効にするオプション名が出る |
feature.PKCE を渡した | 効果がない。上の PKCE の行を参照 |
WithTrustedProxies 未指定で X-Forwarded-* つきのリクエストが届いた | ヘッダは無視される |
WithAllowPrivateNetwork | target ごとに、広げる対象を示す 1 行。INFO だが、オープンな動的クライアント登録か Client ID Metadata Documents も有効な場合、JWKS、JAR、sector、Client ID Metadata、Back-Channel ログアウトの各 target は WARN(SSRF の露出)になる。mTLS / プロキシ / ネットワークを参照 |
WithKeyset の有効な鍵が署名アルゴリズムに合わない場合は、警告ではなくエラーです。2048 ビット以上の RSA 鍵を既定の ES256 のまま渡すと op.New が失敗し、メッセージは to sign with this key, add WithSigningAlgorithm(op.AlgRS256) で終わります。
ここでは設定しないもの
意図的にオプションにしていない項目です。理由は各リンク先の設計判断を参照してください。
- JOSE 検証用の許可リスト — client assertion、JAR request object、DPoP proof など入力側の署名検証では
RS256/PS256/ES256/EdDSAの固定集合を使います。本ライブラリが発行する JWT の署名はES256のみです。どちらの面も広げるフラグはありません。セキュリティ方針 §2 を参照。 - PKCE method —
S256のみ。plainは構造的に拒否されます。 - Cookie scheme —
__Host-プリフィックス、AES-256-GCM、double-submit CSRF が常に有効です。必須オプション § WithCookieKeys を参照。 - 乱数源 —
crypto/randのみ。math/randは lint で禁止しています。 /metricsの公開 — ライブラリではなくルータ側の責務です。ユースケース: Prometheus メトリクス を参照。
このリストの裏取り
カタログはライブラリ本体のソースから取っています。自分で監査するには:
git clone https://github.com/libraz/go-oidc-provider.git
cd go-oidc-provider
grep -hE '^func With[A-Z].*\) Option \{' $(ls op/*.go | grep -v _test.go) | sort -uこのパターンは op.Option を返す関数だけを拾うので、op.New が受け取るオプションが並びます。WithInMemoryDPoPNonceLogger は op.NewInMemoryDPoPNonceSource 用のヘルパーで、op.New のオプションではありません。
関数名と受け取る型のシグネチャが正典であり、各関数の godoc コメントが契約の正本です。