ユースケース — セキュリティプロファイルの宣言
op.WithProfile は OP のセキュリティ姿勢を明示します。未指定も 1 つの選択です。WithProfile なしで構築した OP は profile.OAuth21 で動くため、confidential client を含め、すべての認可コードリクエストに PKCE が必要です。PKCE を送れない RP を受け入れる必要がある配備は、OpenID Connect Core 1.0 の形を保つ profile.OIDCCore を宣言します。
provider, err := op.New(
// issuer、store、keyset、cookie key、client、login flow …
op.WithProfile(profile.OIDCCore), // 全リクエストに PKCE を求める既定から外れる
)profile.OAuth21 が変えるのはこの 1 つの規則だけです。PAR を必須にせず、アクセストークンの有効期間やクライアント認証方式を制限せず、送信者制約付きアクセストークンも要求しません。これらは対象とする FAPI プロファイルの要件であり、本ライブラリの profile.OAuth21 が追加する規則ではありません。対象が FAPI なら FAPI 2.0 Baseline を使ってください。起動ログや監査イベントでは oauth21 と報告され、FAPI 2.0 プロファイルの fapi2-baseline とは別の文字列です。Go の識別子は profile.OAuth21 です。
profile.OIDCCore が追加する要件はなく、confidential client では PKCE が任意のままです。旧来の RP と、OpenID Connect Basic の認定プランのためのものです。他のプロファイルとは組み合わせられず、組み合わせようとすると op.New が失敗します。
構築に成功すると、OP は audit logger へ startup.profile を 1 回出力します。宣言した profile、feature、grant と、解決後のポリシー(署名アルゴリズムの signing_alg、pkce_required、par_required、sender_constrained、client_auth_methods、トークンの有効期間など)が入ります。最初の request を受ける前に、配備した姿勢を確認できます。profile は oauth21、oidc-core、fapi2-baseline、fapi2-message-signing、fapi-ciba の識別子で記録されます。ダッシュボードやアラートではこの文字列で照合してください。
ソース:
examples/00-security-profileは、profile.OIDCCoreの OP とprofile.OAuth21の OP を並べ、同じ confidential client の PKCE 無し request を送ります。
意図して選ぶ
| デプロイの意図 | 設定 |
|---|---|
| OAuth 2.1 の姿勢を取る(既定) | profile を宣言しない。明示するなら op.WithProfile(profile.OAuth21) |
| PKCE を送れない既存の OIDC client との互換性を保つ | op.WithProfile(profile.OIDCCore)。PKCE 移行を計画する |
| Financial-grade API のプロファイルを取る | op.WithProfile(profile.FAPI2Baseline) または該当する FAPI profile |
public / native client はどのプロファイルでも PKCE 必須です。違いが現れるのは confidential client の経路です。
各プロファイルの要件
| プロファイル | PKCE | 自動で有効になる feature | 送信者制約付きトークン | 必須の grant | その他の上限 |
|---|---|---|---|---|---|
profile.OIDCCore | confidential client では任意 | なし | 要求しない | なし | なし。他のプロファイルとは組み合わせられない |
profile.OAuth21(既定) | 必須 | なし | 要求しない | なし | なし |
profile.FAPI2Baseline | 必須 | PAR、JAR | DPoP または mTLS(どちらも未設定なら DPoP) | なし | アクセストークンの有効期間は 10 分以内。PAR の expires_in は 600 秒未満 |
profile.FAPI2MessageSigning | 必須 | PAR、JAR、JARM | DPoP または mTLS | なし | FAPI2Baseline と同じ上限 |
profile.FAPICIBA | 対象外(/auth へのリダイレクトがない) | JAR | DPoP または mTLS | grant.CIBA | FAPI2Baseline と同じ上限 |
出典は op/profile の RequiredFeatures、RequiredAnyOf、RequiredGrants、RequiresPKCE、MaxAccessTokenTTL、PARLifetimeCeiling です。
feature は補われ、grant は補われない
プロファイルは隣り合う 2 つの宣言軸を別々に扱います。この非対称は意図したものです。
どちらの場合も、解決後のポリシーは startup.profile 監査イベントに記録されます。OP が実際にどの設定で起動したかは、オプションの並びから推測するのではなく監査証跡から読み取れます。
足りない feature は自動で有効になります。 PAR や JAR のような feature flag は、プロファイルが決めてよいポリシーだからです。profile.FAPI2Baseline を宣言すれば、必要な feature はオプションを追加しなくても有効になります。
足りない grant は op.New を失敗させます。 grant を有効化すると、組み込み側にしか用意できない協力者が芋づる式に必要になるため、本ライブラリは配備側が求めていないエンドポイントを勝手に mount しません。実際に問題になるのは profile.FAPICIBA です。このプロファイルの主題は /bc-authorize のやり取りそのものですが、そのエンドポイントを mount するのは grant の集合です。この検査が無ければ、プロファイルを宣言して JAR と DPoP が有効になった OP が、backchannel authentication request のすべてに 404 を返す、という状態が成立してしまいます。
provider, err := op.New(
// …
op.WithProfile(profile.FAPICIBA),
op.WithCIBAGrant(op.CIBAGrant{HintResolver: resolver}),
)grant を有効にするのは op.WithCIBAGrant です。grant.CIBA を grant の集合に加え、CIBAGrant.HintResolver などの CIBA 設定を受け取ります。ストアには CIBA リクエスト用のサブストアも必要です。op.WithCIBAGrant なしで profile.FAPICIBA を宣言すると op.New が失敗します。エラーにはプロファイルが要求する grant と、それを有効にするオプションの両方が出るので、メッセージを読めば直せます。op.WithGrants に grant.CIBA を並べるだけでは足りません。hint resolver が未設定のまま、次の検査で失敗するからです。profile.FAPICIBA 以外のプロファイルは、固有の grant を要求しません。