Skip to content

ユースケース — セキュリティプロファイルの宣言 ​

op.WithProfile は OP のセキュリティ姿勢を明示します。未指定も 1 つの選択です。WithProfile なしで構築した OP は profile.OAuth21 で動くため、confidential client を含め、すべての認可コードリクエストに PKCE が必要です。PKCE を送れない RP を受け入れる必要がある配備は、OpenID Connect Core 1.0 の形を保つ profile.OIDCCore を宣言します。

go
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.OIDCCoreconfidential client では任意なし要求しないなしなし。他のプロファイルとは組み合わせられない
profile.OAuth21(既定)必須なし要求しないなしなし
profile.FAPI2Baseline必須PAR、JARDPoP または mTLS(どちらも未設定なら DPoP)なしアクセストークンの有効期間は 10 分以内。PAR の expires_in は 600 秒未満
profile.FAPI2MessageSigning必須PAR、JAR、JARMDPoP または mTLSなしFAPI2Baseline と同じ上限
profile.FAPICIBA対象外(/auth へのリダイレクトがない)JARDPoP または mTLSgrant.CIBAFAPI2Baseline と同じ上限

出典は op/profile の RequiredFeatures、RequiredAnyOf、RequiredGrants、RequiresPKCE、MaxAccessTokenTTL、PARLifetimeCeiling です。

feature は補われ、grant は補われない ​

プロファイルは隣り合う 2 つの宣言軸を別々に扱います。この非対称は意図したものです。

プロファイルは feature を補うが、grant は補わない
プロファイルを宣言すると、それが必要とする feature flag が有効になります。一方で grant は補われません。プロファイルが要求する grant を配備側が宣言していない場合、黙って有効化するのではなく op.New が失敗します。op.WithProfile(…)feature: 補われるfeature.PAR · feature.JAR · …プロファイルが単独で決めてよいポリシー未宣言 → プロファイルが有効化するgrant: 補われないgrant.AuthorizationCode · grant.CIBA · …必要な協力者を用意できるのは組み込み側だけ未宣言 → op.New が失敗する
この非対称は意図したものです。feature はプロファイルが単独で強制できる規則ですが、grant には認証器やストア、場合によっては通知チャネルが要ります。用意できるのは組み込み側だけなので、黙って有効化すれば、受け付けたリクエストを完了できない OP ができあがります。

どちらの場合も、解決後のポリシーは 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 を返す、という状態が成立してしまいます。

go
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 を要求しません。