監査イベントカタログ
OP は op/audit パッケージで閉じたカタログとして定義された、構造化された監査イベントを発火します。ただしカタログは語彙であり、すべての定数が発火するという約束ではありません。本ページでは OP が発火するシグナルと、将来または組み込み側の account/device plane 向けに予約された名前を区別します。各イベントは <area>.<verb>(または <area>.<verb>.<qualifier>)形の安定した文字列です。SOC ダッシュボードは自由形式のメッセージを解析しなくても、area 単位で集計できます。
購読する
op.New(
/* 必須オプション */
op.WithAuditLogger(slog.New(myJSONHandler)),
)op.WithAuditLogger は *slog.Logger を受け取ります。各イベントは構造化ログのエントリとして記録されます。event 属性はイベント識別子(たとえば "token.issued")を、msg は人間向けの短いメッセージを持ちます。正規フィールドは任意のトップレベル属性です。actor_id、client_id、session_id、request_id、ip、user_agent、tag は未設定なら出力されません。空でない extras グループにカテゴリ固有のフィールドが入ります。発火は呼び出し元の goroutine 上で同期的に行われます。handler は遅い I/O や無制限 queue で block させず、多数の request から並行して呼ばれても安全にしてください。
WithAuditLogger を渡さない場合は、WithLogger で設定したロガーに流れます。どちらも渡していない場合、監査イベントは破棄されます。
Prometheus にも同時に送る
WithPrometheus を併用すると、これらのイベントの厳選サブセットが Prometheus カウンタにも反映されます。1 回の発火で slog のストリームと該当カウンタの両方が更新されるので、metrics 用の追加発火はありません。
コードからカタログを列挙する
監査イベントの定数と、OP が使うイベントのレジストリは、github.com/libraz/go-oidc-provider/op/audit パッケージで公開されています(audit.LoginSuccess、audit.TokenIssued など。文字列値は以下のイベント名です)。audit.Catalog() は全イベントのコピーを []audit.EventDefinition として返します:
import "github.com/libraz/go-oidc-provider/op/audit"
for _, def := range audit.Catalog() {
// def.Event — 監査イベント識別子。例: "token.issued"
// def.MetricName — 対応する Prometheus カウンタ。監査のみのイベントでは空
// def.MetricLabel — カテゴリカウンタで使う値域限定のラベル。空のことも多い
}イベント集合を散文ではなくデータとして扱いたいとき、たとえば SIEM のルールを生成する、ダッシュボードが全イベントを網羅していることをテストで検証する、metrics 投影を持つイベントを洗い出す、といった場面で使います。ライブラリ内の発火箇所と Prometheus ブリッジが同じレジストリを参照しているため、イベントの一覧と metrics のルーティングが食い違うことはありません。
共通の属性
発火したイベントには audit と event が含まれます。正規フィールドは任意で、未設定なら出力されません。extras は空なら出力されません。slog.JSONHandler を使うと、レコード時刻、レベル、メッセージも出力されます:
| 属性 | 型 | 補足 |
|---|---|---|
audit | string | 常に "true" |
event | string | イベント識別子。例: "token.issued" |
actor_id | string | ユーザ起点では subject 識別子、クライアント起点では client_id。未設定なら出力されません |
client_id | string | OAuth client_id。未設定なら出力されません |
session_id | string | 該当する場合の OP session 識別子。未設定なら出力されません |
request_id | string | リクエストの相関 ID。未設定なら出力されません |
ip | string | OP のエッジで観測したクライアント IP。未設定なら出力されません |
user_agent | string | 観測した User-Agent の値。未設定なら出力されません |
tag | string | operator が設定した DCR tag。未設定なら出力されません |
extras | group | カテゴリ固有のフィールド(各セクションを参照)。空の場合は出力されません |
time | timestamp | slog.Record.Time。WithClock またはシステム時刻のレコード時刻です |
level | string | slog.Record.Level。INFO、WARN、ERROR など |
msg | string | slog.Record.Message。人間向けの短いメッセージです |
イベントカタログ
カタログを機能領域ごとに再編成しました。各グループは、SOC や運用にとってこの一群のイベントが何を意味するかを短く述べたあと、event 定数(op/audit パッケージの Go 識別子)、発火タイミングまたは予約理由、想定シビアリティ(info は通常運転、warn は怪しい / 失敗系、alert は replay やストア障害といった即応すべきシグナル、という大まかな目安)、関連ページ の表に落としています。予約 と明記した行は OP が発火しません。予約イベントが存在しないことは、元の操作が起きなかった証拠ではありません。
Provider ライフサイクル
startup.profile は OP instance の監査ストリームの起点です。op.New が設定を検証し、provider を返す前に 1 回だけ発火します。extras は次の 2 群で構成されます。
- 宣言値 —
profiles/features/grants。profilesは宣言順の小文字の識別子(oauth21、oidc-core、fapi2-baseline、fapi2-message-signing、fapi-ciba)です。op.WithProfileを指定しない場合は["oauth21"]になります。 - 解決後のポリシー —
signing_alg(ES256またはRS256)、PKCE、PAR、nonce と state-or-nonce、送信者制約、client authentication、token TTL、token format、リフレッシュの猶予期間とローテーション、DPoP nonce、JAR、署名付き backchannel request、JARM、署名付き introspection、および 2 つのinsecure_*_for_devフラグ。
| event 定数 | 発火タイミング | 想定シビアリティ | 関連ページ |
|---|---|---|---|
audit.StartupProfile | 検証済み provider の起動時 | info | Options 索引 |
アカウント管理
予約語です。 OP が直接ホストしない仕様外の管理経路(プロビジョニング / リカバリ / フェデレーションリンクなど)を表します。組み込み側は自身の監査 sink から発火できますが、OP 自体は発火しません。
| event 定数 | 発火タイミング | 想定シビアリティ | 関連ページ |
|---|---|---|---|
audit.AccountCreated | 予約 — 組み込み側がユーザアカウントを払い出した | info | — |
audit.AccountDeleted | 予約 — 組み込み側がユーザアカウントを削除した | info | — |
audit.AccountEmailAdded | 予約 — アカウントに email を追加した | info | — |
audit.AccountEmailVerified | 予約 — email の所有を確認した | info | — |
audit.AccountEmailRemoved | 予約 — email を削除した | info | — |
audit.AccountEmailSetPrimary | 予約 — プライマリ email を変更した | info | — |
audit.AccountPasskeyRegistered | 予約 — WebAuthn credential を登録した | info | — |
audit.AccountPasskeyRemoved | 予約 — WebAuthn credential を削除した | info | — |
audit.AccountTOTPEnabled | 予約 — TOTP 登録を完了した | info | — |
audit.AccountTOTPDisabled | 予約 — TOTP を解除した | info | — |
audit.AccountPasswordChanged | 予約 — パスワードを変更した | info | — |
audit.AccountRecoveryRegenerated | 予約 — recovery batch を再発行した | info | — |
audit.RecoverySupportEscalation | 予約 — サポートによる override / 手動 recovery | warn | — |
audit.AccountFederationLinked | 予約 — 外部 IdP の credential を連携した | info | — |
audit.AccountFederationUnlinked | 予約 — 外部 IdP の credential 連携を解除した | info | — |
ログイン / MFA / step-up
login.* と mfa.* は、factor が解決したあとに authenticator chain から発火します。chain の最初の factor は login.*、2 つ目以降は mfa.* で報告されます。既存セッションでの step-up も mfa.* で、セッションが持つ過去の認証方式は完了済みとして数えられます。login.failed / mfa.failed は通常レベルの探索シグナルで、レートが恒常的に上がるようなら credential stuffing の典型的な兆候です。WithAuthnLockoutStore を使っている場合、ロックアウトを発動させた失敗した試行も、これらの失敗イベントとして報告され、続けて lockout.engaged が発火します。audit.MFARequired、audit.StepUpRequired、audit.StepUpSuccess は 予約 であり、OP は発火しません。step-up は resource server が決め、OP には通常の authorize request が届きます。
| event 定数 | 発火タイミング | 想定シビアリティ | 関連ページ |
|---|---|---|---|
audit.LoginSuccess | プライマリ credential の検証が成功し、subject が確定した | info | ユースケース: MFA / ステップアップ |
audit.LoginFailed | プライマリ credential が拒否された | warn | ユースケース: MFA / ステップアップ |
audit.LockoutStalled | cross-factor lockout の CAS 競合で失敗試行をカウントせず中断した。その subject の失敗回数の枠は進まない | alert | ユースケース: MFA / ステップアップ |
audit.LockoutEngaged | 失敗した試行によって、cross-factor の総当たり対策ロックが新たに成立した(password、TOTP、メール OTP、recovery code)。subject を ActorID として 1 回だけ発火し、ロック中の試行では再発火しない。ロック中のパスワード試行は誤ったパスワードとまったく同じ応答になるため、このイベントが「ユーザがログインできない」ことを運用者に知らせる合図になる | warn | ユースケース: MFA / ステップアップ |
audit.StepBeginFailed(login.step_begin_failed) | login flow の step が開始できなかった。プロンプトを出す前に拒否する factor でも記録が残る。extras は step_kind と reason(not_enrolled、aborted、locked、not_enrolled_skipped、error)を持つ。subject が確定していれば actor_id に入り、クライアントが中断したリクエストは記録しない | warn(not_enrolled_skipped は info。one-of step が、subject がどの factor も持たないために通過された場合) | ユースケース: MFA / ステップアップ |
audit.MFARequired | 予約 — OP は requirement 専用イベントを発火しない | info | ユースケース: MFA / ステップアップ |
audit.MFASuccess | 第 2 factor が受理された | info | ユースケース: MFA / ステップアップ |
audit.MFAFailed | 第 2 factor が拒否された | warn | ユースケース: MFA / ステップアップ |
audit.StepUpRequired | 予約 — resource server の判断であり、OP は発火しない | info | ユースケース: MFA / ステップアップ |
audit.StepUpSuccess | 予約 — resource server の結果であり、OP は発火しない | info | ユースケース: MFA / ステップアップ |
extras
factor—password、passkey、totp、email_otp、captcha、recovery_code、または user-defined Step kind
login/MFA イベントは aal、acr、amr_values を持ちません。
同意
audit.ConsentGranted と audit.ConsentGrantedFirstParty は同意画面とファーストパーティの自動同意経路から発火します。その他の consent 定数は 予約 です。追加 scope の同意も通常の consent.granted として記録され、既存 grant の再利用にはイベントがなく、grant の取り下げには Grant Management の grant_management.revoked を使います。
| event 定数 | 発火タイミング | 想定シビアリティ | 関連ページ |
|---|---|---|---|
audit.ConsentGranted | ユーザが同意画面で同意した | info | ガイド: 同意 |
audit.ConsentGrantedFirstParty | ファーストパーティの自動同意を適用した(同意画面なし) | info | ユースケース: ファーストパーティ同意スキップ |
audit.ConsentGrantedDelta | 予約 — 追加 scope は通常の audit.ConsentGranted として発火 | info | ガイド: 同意 |
audit.ConsentSkippedExisting | 予約 — 保存済み同意の再利用は発火しない | info | ガイド: 同意 |
audit.ConsentRevoked | 予約 — Grant Management の取り下げは audit.GrantManagementRevoked を発火 | info | ガイド: 同意 |
extras
grant_id— consent を記録した grantscope— コードを発行したときの scopecompletion_id— ブラウザが RP へ運ぶ認可コードの不可逆な fingerprint
code / token のライフサイクル
認可コード発行パスと token endpoint から発火します。replay 検出系(code.replay_detected、refresh.replay_detected)とサブストア障害系(token.revoke_failed、refresh.chain_revoke_failed、refresh.grant_revoke_failed)が高シグナルなアラートで、それ以外は通常運転のライフサイクル telemetry です。
| event 定数 | 発火タイミング | 想定シビアリティ | 関連ページ |
|---|---|---|---|
audit.CodeIssued | 認可コードを発行した。対話的経路とサイレント経路を含め、コードごとに 1 回だけ発火します | info | ガイド: 認可コード + PKCE |
audit.CodeConsumed | /token で code を消費した | info | ガイド: 認可コード + PKCE |
audit.CodeReplayDetected | 認可コードが二度提示された — chain を失効させる | alert | ガイド: 認可コード + PKCE |
audit.TokenIssued | grant に対する最初の refresh token を永続化した(すべての access token 発行を数えるイベントではない) | info | ガイド: トークン |
audit.TokenRefreshed | リフレッシュトークンをローテーションし、そのローテーションが永続化された。並行する提示にコミット時に負けた refresh やロールバックした refresh では記録されない | info | ガイド: リフレッシュトークン |
audit.TokenRevoked | /revoke がトークンを失効させた。対象 grant の subject がすでに存在しないため /token が引き換えを拒否したときにも、warn レベルで記録される | info | ガイド: トークン |
audit.TokenRevokeFailed | 失効処理がサブストアの障害を観測。RFC 7009 §2.2 により、通信路上の応答は 200 のまま | alert | ガイド: トークン |
audit.RefreshReplayDetected | リフレッシュトークンがローテーション猶予を超過して提示された — chain を失効させる | alert | ガイド: リフレッシュトークン |
audit.RefreshChainRevokeFailed | replay 検出時の連鎖失効でサブストアの障害を観測 | alert | ガイド: リフレッシュトークン |
audit.RefreshGrantRevokeFailed | refresh-rotation cascade で grant tombstone の書き込みが失敗 | alert | ガイド: リフレッシュトークン |
audit.RefreshPriorAccessTokenRevokeFailed | refresh rotation で直前の access token を失効できなかった。retry 可否も extras に入る | alert | ガイド: リフレッシュトークン |
code_id と completion_id は認可コード識別子から作る不可逆な fingerprint です。相関用の値であり、生の認可コードや内部識別子ではありません。code.issued は発行したコードごとに 1 回だけ発火します。
extras
refresh_origin— refresh chain に記録された型付き origin。authorization_code、device_code、ciba、custom_grantのいずれかで、欠落または閉じた集合外は metrics bridge がunknownに投影します。任意の requestgrant_typelabel ではなく、実際に chain を発行した grant を表しますgrant_id—token.issued・token.refreshed・token.revoked・code.*では、そのクレデンシャルが属する grant。token.revoke_failed(token endpoint)とrefresh.grant_revoke_failedでは、teardown に失敗した grantscope—code.issuedとcode.consumedで、コードの scopecode_id—code.*で、認可コードの不可逆な fingerprintoffline_access—token.issuedとtoken.refreshedで、bool。offline_accesschain なら truettl_bucket—token.issuedとtoken.refreshedで、どの refresh token 有効期間が適用されたかsurface—token.revokedではjwt_access_token、opaque_access_token、refresh_chain、refresh_grant(chain の起点を解決できず、/revokeが grant の refresh token の失効に切り替えた)。subject が存在しないため引き換えを拒否した場合はsubject_deprovisioned。token.revoke_failedでは障害を観測した段階で、たとえばrefresh_chain_walk、refresh_chain、refresh_grant、opaque_access_token_lookup。token endpoint は連鎖失効の名前を前置し、code_replay_jwt_access_tokensのようになるjti— JWT アクセストークンのtoken.revokedでreason—refresh.chain_revoke_failed/refresh.grant_revoke_failedで、サブストアから返ったエラー文字列err—token.revoke_failedで、サブストアから返ったエラー文字列failure_stage、retryable—refresh.prior_access_token_revoke_failedの値
セッション / ログアウト
下記のセッション / ログアウトの行は、セッションマネージャ、/end_session、detached Back-Channel Logout coordinator から発火します。audit.LogoutRPInitiated は 予約 です。/end_session は RP が要求したという marker ではなく、セッションと配送の結果を記録します。
| event 定数 | 発火タイミング | 想定シビアリティ | 関連ページ |
|---|---|---|---|
audit.SessionCreated | 新しいブラウザセッションを発行した(ログイン後) | info | ガイド: セッションとログアウト |
audit.SessionDestroyed | session を削除した(logout / 期限切れ / 退避) | info | ガイド: セッションとログアウト |
audit.SessionAlreadyAbsent | ログアウト対象の session がすでに無い、または期限切れだった | info | ガイド: セッションとログアウト |
audit.SessionDestroyFailed | session 削除が store 障害になった。リクエストは静的 503 で状態を保持する | alert | ガイド: セッションとログアウト |
audit.LogoutClientLookupFailed | RP 起点ログアウトの解決中に client registry の store lookup が失敗した。通信路上の応答は汎用的なまま | alert | ガイド: セッションとログアウト |
audit.LogoutRPInitiated | 予約 — RP が要求したことだけを示す marker は発火しない | info | ガイド: セッションとログアウト |
audit.LogoutTokenRevokeFailed | logout token またはログアウト cascade の失効で store 障害になった | alert | ガイド: セッションとログアウト |
audit.LogoutBackChannelDelivered | Back-Channel logout token を RP に配送した | info | ユースケース: バックチャネルログアウト |
audit.LogoutBackChannelFailed | Back-Channel 配送に失敗(HTTP エラー / タイムアウト / 検証失敗) | warn | ユースケース: バックチャネルログアウト |
audit.LogoutBackChannelResolveFailed | grant ベースの通知先解決に失敗した | alert | ユースケース: バックチャネルログアウト |
audit.LogoutBackChannelOverflow | 上限付き通知先解決が overflow した | warn | ユースケース: バックチャネルログアウト |
audit.BCLNoSessionsForSubject | session-bearing /end_session notice で grant 由来の RP 対象が 0 件(通知する RP がない) | info | ユースケース: バックチャネルログアウト |
bcl.no_sessions_for_subject の意図
このイベントは Notice.SessionID があり、grant ベースの audience 解決で RP 対象が 0 件になった場合だけ発火します。coordinator が SessionStore を辿った、または session が追い出されたことを意味しません。SessionStore が /end_session の snapshot 前に行を失うと、handler は detached fan-out を起動せず、このイベントも発火しません。grant 由来の対象 0 件は通常の no-op でも起きるため INFO レベルとし、SOC ツールは個別イベントではなく発生レートの上昇に対してアラートを張ります。設定された WithSessionDurabilityPosture の値は trigger / snapshot の喪失と対象 0 件を解釈する文脈として含まれます。
防御シグナル
下記では PKCE、redirect mismatch、CORS、(loose verifier の opt-in 時の)DPoP、retired key のシグナルを OP が発火します。rate-limit は 組み込み側向け予約語 です。legacy algorithm の定数は 予約語 であり、OP は拒否を返しますが監査イベントは発火しません。
| event 定数 | 発火タイミング | 想定シビアリティ | 関連ページ |
|---|---|---|---|
audit.RateLimitExceeded | レートリミッタがリクエストを拒否した — 組み込み側が発火 する語彙。本ライブラリは汎用の per-IP / per-endpoint HTTP throttle を実装しません | warn | — |
audit.RateLimitBypassed | bypass トークンを消費した(運用者による上書き) — 組み込み側が発火 する語彙。スコープは audit.RateLimitExceeded と同じ | warn | — |
audit.PKCEViolation | /token で code_verifier の検証に失敗した。extras には endpoint と reason(verifier_mismatch、verifier_format、challenge_method_unsupported)が入り、verifier そのものは入らない | warn | ガイド: 認可コード + PKCE |
audit.RedirectURIMismatch | /authorize に未登録の redirect_uri が来た、または /token に認可リクエストと異なる値が来た。extras には endpoint と受け取った redirect_uri が入る。/token の応答は汎用の invalid_grant のままなので、原因はこのイベントで確認する | warn | ガイド: Redirect URI |
audit.AlgLegacyUsed | 予約 — 旧 alg の telemetry を発火する OP パスはない | warn | ガイド: JOSE 基礎 |
audit.CORSPreflightAllowed | CORS preflight が厳格な許可リストに合致した | info | ユースケース: SPA 向け CORS |
audit.DPoPLooseMethodCaseAdmitted | 条件付き — loose method-case bridge を設定した verifier のみ発火。標準 op.New は strict | info | ガイド: DPoP |
audit.KeyRetiredKidPresented | リクエストが JWKS の猶予期間を過ぎた kid を提示 — verifier で拒否 | warn | 運用: 鍵ローテーション |
対話画面(interaction)
interaction driver が応答を commit する前に render に失敗した場合だけ、render failure signal を発火します。driver が応答を commit 済みなら、OP は応答を置き換えられないため、重複イベントを発火しません。
| event 定数 | 発火タイミング | 想定シビアリティ | 関連ページ |
|---|---|---|---|
audit.InteractionRenderFailed | interaction driver の render が応答 commit 前に失敗した。OP は汎用の server_error ページを返す | alert | ユースケース: SPA / 対話画面のカスタマイズ |
introspection
/introspect がクライアント認証を拒否したとき、または opaque access token / refresh token の store lookup が失敗したときに発火します。正常な inactive miss ではエラーイベントを発火しません。NotFound 以外の lookup 障害では、監査イベントで障害を把握しつつ、RFC 7662 の通信路上の応答は HTTP 200 と {"active":false} のままです。クライアント認証失敗は従来の標準エラー応答です。
| event 定数 | 発火タイミング | 想定シビアリティ | 関連ページ |
|---|---|---|---|
audit.IntrospectionError | /introspect がクライアント資格情報を拒否した、または opaque token store が NotFound 以外の障害を返した | warn / alert | 運用: 可観測性 |
クライアント認証
/token、/par、/device_authorization、/bc-authorize がクライアント認証を拒否したときに発火します。通信路上の応答は標準どおりの invalid_client のままに保ちつつ、このイベントから試行された client_id と短い理由コードを取り出せます。/introspect は audit.IntrospectionError、/revoke はこのイベントを使いません。
| event 定数 | 発火タイミング | 想定シビアリティ | 関連ページ |
|---|---|---|---|
audit.ClientAuthnFailure | /token、/par、/device_authorization、/bc-authorize がクライアントを拒否(誤った secret、期限切れ assertion、alg 不一致、private_key_jwt の不在など) | warn | ガイド: クライアント種別 |
audit.ClientAuthnPreviousSecret(client_authn.previous_secret) | クライアントが、ローテーションの猶予期間中に旧 secret で client_secret_basic または client_secret_post の認証を行った。extras["method"] が方式を示し、secret 自体は添付しない。猶予期間が閉じる前に切り替えが必要なクライアントを見つけるために使う | warn | ガイド: クライアント種別 |
Client ID Metadata Document
Experimental(op.WithClientIDMetadataDocuments と同じ)。URL 形式の client_id を OP が解決するときに発火します(MCP 認可サーバを参照)。
| event 定数 | 発火タイミング | 想定シビアリティ | 関連ページ |
|---|---|---|---|
audit.CIMDFetched(cimd.fetched) | client ID metadata document を取得し、検証した | info | ユースケース: MCP 認可サーバ |
audit.CIMDFetchFailed(cimd.fetch_failed) | document の取得または検証に失敗した。extras["reason"] は status、network、too_large、content_type、json、validation のいずれかで、validation では extras["error_code"] に検証エラーコードが入る | warn | ユースケース: MCP 認可サーバ |
audit.CIMDClientDenied(cimd.client_denied) | ClientIDMetadataDocuments.Allow フックが client_id URL を拒否した | warn | ユースケース: MCP 認可サーバ |
動的クライアント登録(DCR)
/register および /register/{client_id} から発火します。RAT / IAT 系の失敗イベントは、DCR 配下では probing の典型的なシグナルです。
| event 定数 | 発火タイミング | 想定シビアリティ | 関連ページ |
|---|---|---|---|
audit.DCRIATConsumed | Initial Access Token を消費した | info | ユースケース: 動的クライアント登録 |
audit.DCRIATExpired | TTL 超過の IAT を提示した | warn | ユースケース: 動的クライアント登録 |
audit.DCRIATInvalid | IAT の signature / format が不正 | warn | ユースケース: 動的クライアント登録 |
audit.DCROpenRegistrationUsed | open(IAT 不要)登録を受理した | info | ユースケース: 動的クライアント登録 |
audit.DCRClientRegistered | 新規 client を作成した | info | ユースケース: 動的クライアント登録 |
audit.DCRClientMetadataRead | RAT 持ちの GET on /register/{client_id} | info | ユースケース: 動的クライアント登録 |
audit.DCRClientMetadataUpdated | RAT 持ちの PUT on /register/{client_id} | info | ユースケース: 動的クライアント登録 |
audit.DCRClientDeleted | RAT 持ちの DELETE on /register/{client_id} | info | ユースケース: 動的クライアント登録 |
audit.DCRRATInvalid | Registration Access Token を拒否した | warn | ユースケース: 動的クライアント登録 |
audit.DCRMetadataValidation | メタデータペイロードがポリシー違反 | warn | ユースケース: 動的クライアント登録 |
audit.DCRCascadeRefreshRevokeFailed | client 削除時に refresh-token 行の失効に失敗 | alert | ユースケース: 動的クライアント登録 |
audit.DCRCascadeGrantRevokeFailed | client 削除時に grant の失効に失敗 | alert | ユースケース: 動的クライアント登録 |
audit.DCRCascadeAccessTokenRevokeFailed | client 削除時に JWT access-token 行の失効に失敗 | alert | ユースケース: 動的クライアント登録 |
audit.DCRCascadeOpaqueAccessTokenRevokeFailed | client 削除時に opaque access-token 行の失効に失敗 | alert | ユースケース: 動的クライアント登録 |
Device Code (RFC 8628)
/device_authorization、op/devicecodekit の verification ヘルパ、token endpoint の device-code grant から発火します。device_code.verification.user_code_brute_force と device_code.token.slow_down は、典型的なポーリング乱用シグナルです。
| event 定数 | 発火タイミング | 想定シビアリティ | 関連ページ |
|---|---|---|---|
audit.DeviceAuthorizationIssued | /device_authorization が新しい device_code + user_code ペアを返却 | info | ガイド: Device Code |
audit.DeviceAuthorizationRejected | /device_authorization がリクエストを拒否(未知 client、scope 拒否など) | warn | ガイド: Device Code |
audit.DeviceAuthorizationUnboundRejected | DPoP / mTLS の証明が必要だが /device_authorization に無かった | warn | ガイド: 送信者制約付きトークン |
audit.DeviceCodeVerificationApproved | 組み込み側の verification ページがユーザの承認を報告 | info | ユースケース: Device Code |
audit.DeviceCodeVerificationDenied | 組み込み側の verification ページがユーザ拒否を報告(またはレコード単位の総当たり対策がロックアウト) | warn | ユースケース: Device Code |
audit.DeviceCodeUserCodeBruteForce | user_code 提出が外れた。カウンタを増やし、devicecodekit.MaxUserCodeStrikes(既定 5)でロックアウト発火 | alert | ユースケース: Device Code |
audit.DeviceCodeTokenIssued | 承認済 device authorization に対し /token がトークンを発行 | info | ユースケース: Device Code |
audit.DeviceCodeTokenRejected | /token が device-code grant を拒否(access_denied、expired_token など) | warn | ユースケース: Device Code |
audit.DeviceCodeTokenSlowDown | /token が slow_down を返し、サブストア上のポーリング間隔に 5 秒を加算 | warn | ユースケース: Device Code |
audit.DeviceCodeRevoked | op/devicecodekit.Revoke がレコードを拒否状態に遷移させた。ヘルパは device flow が確保した grant 配下で連鎖失効させる。extras には試行した面ごとの結果(cascade_complete、revoked_access_tokens、grant_tombstone_written、revoked_opaque_access_tokens、refresh_token_cascade_complete)が入り、任意の Deps.Grants を渡した場合は grant_record_deleted も入る | info | ユースケース: Device Code |
audit.DeviceCodePollObservationFailed | ポーリングの LastPolledAt 永続化が失敗。判定自体は続行する(best-effort な観測) | warn | ユースケース: Device Code |
CIBA
/bc-authorize と token endpoint の CIBA grant から発火します。ciba.poll_abuse.lockout がクライアントの不正挙動を捕まえる主要シグナルです。authentication-device の approve / deny 定数は 予約 です。組み込み側が CIBARequestStore.Approve / Deny を直接呼ぶため、OP の発火点がありません。
| event 定数 | 発火タイミング | 想定シビアリティ | 関連ページ |
|---|---|---|---|
audit.CIBAAuthorizationIssued | /bc-authorize が新しい auth_req_id を返却 | info | ガイド: CIBA |
audit.CIBAAuthorizationRejected | /bc-authorize がリクエストを拒否(未知ユーザ、ヒントリゾルバ失敗、scope 拒否) | warn | ガイド: CIBA |
audit.CIBAAuthorizationUnboundRejected | DPoP / mTLS の証明が必要だが /bc-authorize に無かった | warn | ガイド: 送信者制約付きトークン |
audit.CIBAAuthDeviceApproved | 予約 — 組み込み側 callback が直接 Approve を呼ぶため OP は観測しない | info | ユースケース: CIBA |
audit.CIBAAuthDeviceDenied | 予約 — 組み込み側 callback が直接 Deny を呼ぶため OP は観測しない | warn | ユースケース: CIBA |
audit.CIBAPollAbuseLockout | ポーリング間隔が交渉済みの interval を大きく下回り続け、リクエストをロックアウト | alert | ユースケース: CIBA |
audit.CIBATokenIssued | 承認済 CIBA リクエストに対し /token がトークンを発行。引き換えは grant を記録するため、同じ scope への次回以降のリクエストは consent 画面を省略する | info | ユースケース: CIBA |
audit.CIBATokenRejected | /token が CIBA grant を拒否(access_denied、expired_token、authorization_pending) | warn | ユースケース: CIBA |
audit.CIBATokenSlowDown | /token が slow_down を返却。クライアントが交渉 interval より速くポーリングした | warn | ユースケース: CIBA |
audit.CIBAPollObservationFailed | ポーリングの LastPolledAt 永続化が失敗。判定自体は続行する(best-effort な観測) | warn | ユースケース: CIBA |
Token Exchange (RFC 8693)
同梱の WithTokenExchangeGrant ハンドラから発火します。requested は parse と構造検証より前の handler 入口で発火するため、構造上の拒否も含みます。成功時は requested + granted を発火します。granted と refresh_issued は発行に成功したあとにだけ記録し、発行に失敗した場合は代わりに custom_grant.failed を記録します。後段の拒否時は requested + 失敗系イベント 1 つを発火します。policy_denied / scope_inflation_blocked / audience_blocked が、SOC ダッシュボードで通常追うポリシー判定シグナルです。
| event 定数 | 発火タイミング | 想定シビアリティ | 関連ページ |
|---|---|---|---|
audit.TokenExchangeRequested | /token が RFC 8693 の試行を exchange handler に dispatch した。parse と構造検証より前 | info | ガイド: Token Exchange |
audit.TokenExchangeGranted | exchange を許可し、発行も成功した。トークンの発行後にだけ記録する | info | ユースケース: トークン交換 |
audit.TokenExchangePolicyDenied | 組み込み側の TokenExchangePolicy が拒否(deny)を返却 | warn | ユースケース: トークン交換 |
audit.TokenExchangePolicyError | ポリシーが拒否(deny)以外のエラーを返却(一過性のインフラ障害など) | warn | ユースケース: トークン交換 |
audit.TokenExchangeScopeInflationBlocked | 要求 scope が subject_token の scope または client 許可リストを超えた | warn | ユースケース: トークン交換 |
audit.TokenExchangeAudienceBlocked | 要求 audience がポリシーの許可リストの外だった | warn | ユースケース: トークン交換 |
audit.TokenExchangeTTLCapped | 発行 TTL を(ハンドラの希望、subject_token の残り、グローバル上限)の最小値で切り詰めた | info | ユースケース: トークン交換 |
audit.TokenExchangeActChainTooDeep | subject_token のネストした act チェーンが 5 段の深さ上限を超えた。policy の実行前に検査する | warn | ユースケース: トークン交換 |
audit.TokenExchangeEmptyScopeRejected | scope subset を空集合に解決して拒否 | warn | ユースケース: トークン交換 |
audit.TokenExchangeActorEqualsSubject | actor_token が subject_token と同じ subject に解決。exchange は invalid_request で拒否 | info | ユースケース: トークン交換 |
audit.TokenExchangeSubjectTokenExternal | subject_token がローカルレジストリで解決できず、外部発行の opaque トークンとして扱った | info | ユースケース: トークン交換 |
audit.TokenExchangeActorTokenExternal | actor_token がローカルレジストリで解決できず、外部発行の opaque トークンとして扱った | info | ユースケース: トークン交換 |
audit.TokenExchangeSubjectTokenInvalid | subject_token の検証に失敗(signature / TTL / cnf 不一致) | warn | ユースケース: トークン交換 |
audit.TokenExchangeSubjectTokenRegistryError | レジストリの参照(lookup)が NotFound 以外の障害を観測。通信路上の応答は invalid_grant のまま | alert | ユースケース: トークン交換 |
audit.TokenExchangeRefreshIssued | exchange が refresh 発行を明示し(IssueRefreshToken=op.PtrBool(true))、refresh token を発行した | info | ユースケース: トークン交換 |
audit.TokenExchangeSelfExchange | actor_token なしで、subject_token の発行先が呼び出し client 自身(self-exchange。act claim は付かない) | info | ユースケース: トークン交換 |
audit.TokenExchangeIDJAGIssued(token_exchange.idjag_issued) | ID-JAG の token exchange に対して ID-JAG を発行した。応答の書き込み後に 1 回記録する。extras は audience、aud_client_id、granted_scope、resource、ttl_seconds、ID-JAG の jti | info | ユースケース: トークン交換 |
JWT bearer grant (RFC 7523)
/token の urn:ietf:params:oauth:grant-type:jwt-bearer grant から、plain と ID-JAG の両プロファイルで発火します。拒否の reason は、失敗した検証ステージ(parse、issuer、typ、signature、claims、idjag、replay)か、token endpoint 側の検査(たとえば public_client、missing_assertion、client_not_allowed、scope、resource、binding、unknown_subject、key_source_unavailable、verifier_fault)です。
| event 定数 | 発火タイミング | 想定シビアリティ | 関連ページ |
|---|---|---|---|
audit.JWTBearerGranted(jwt_bearer.granted) | assertion を償還してアクセストークンを発行した。extras は assertion の issuer と profile、actor は解決した subject | info | ユースケース: トークン交換 |
audit.JWTBearerRejected(jwt_bearer.rejected) | 償還を拒否した。extras は reason、assertion の iss を読んだあとなら issuer も含む | info | ユースケース: トークン交換 |
カスタム grant
dispatcher は登録済みの custom handler に到達したすべての dispatch 試行について、成功と handler を呼ぶ前の gate 失敗を含め、入口で custom_grant.requested を発火します。未登録の grant_type は custom-grant dispatch の入口に到達する前に返るため、custom-grant の監査イベントは発火しません。失敗時は 1 つの失敗出口から custom_grant.failed を 1 回発火します。handler の panic は recover され、panic の情報を extras に含む同じ失敗イベント 1 回になります。
| イベント | 意味 | レベル | 参照 |
|---|---|---|---|
audit.CustomGrantRequested (custom_grant.requested) | 登録済み custom handler に到達したすべての dispatch 試行(handler 前の gate 失敗も含む) | info | ユースケース: カスタム grant |
audit.CustomGrantFailed (custom_grant.failed) | custom grant の dispatch または handler が失敗した。panic を recover した場合も、試行ごとに 1 回だけ発火します | warn | ユースケース: カスタム grant |
audit.CustomGrantRefreshDropped (custom_grant.refresh_dropped) | ハンドラが IssueRefreshToken でリフレッシュトークン発行を求めたが、クライアントが refresh_token grant に登録されていない。アクセストークン応答自体は成功する | info | ユースケース: カスタム grant |
Grant management
OAuth 2.0 Grant Management endpoint のイベントです。認証済み revoke request の grant cascade が完了しないときは failure シグナルが発火します。
| イベント定数 | 発火タイミング | severity の目安 | リンク先 |
|---|---|---|---|
audit.GrantManagementRevoked | grant management エンドポイントへの DELETE が grant を失効させ、トークンをカスケードした | info | ユースケース: Grant management |
audit.GrantManagementRevokeFailed | DELETE の認証後、grant の失効副作用が失敗した | alert | ユースケース: Grant management |
Shared Signals
op.WithSharedSignals で有効にした Shared Signals transmitter から発火するイベントです(Shared Signals を参照)。いずれも metrics は更新しません。配送系のイベントは extras に stream_id、jti、kind、event_type を持ちます。
| イベント定数 | 発火タイミング | severity の目安 | リンク先 |
|---|---|---|---|
audit.SSFStreamCreated(ssf.stream.created) | Receiver が stream を作成した | info | 運用: Shared Signals |
audit.SSFStreamUpdated(ssf.stream.updated) | Receiver が stream を更新・置換した、または status を変更した | info | 運用: Shared Signals |
audit.SSFStreamDeleted(ssf.stream.deleted) | Receiver が stream を削除した。キューに残っていたイベントはすべて破棄される | info | 運用: Shared Signals |
audit.SSFSETEnqueued(ssf.set.enqueued) | Security Event Token を stream のキューに入れた。extras は stream_id、jti、event_type、delivery、held | info | 運用: Shared Signals |
audit.SSFEnqueueFailed(ssf.enqueue_failed) | イベントを Receiver のキューに入れられなかった。イベントの発生元の操作(ログアウトや RevokeSubject)は失敗させない。extras["reason"] が原因を示し、fanout_capacity は subject の Receiver 数が 1 回のファンアウトで読める上限を超えたことを表す | alert | 運用: Shared Signals |
audit.SSFPushDelivered(ssf.push_delivered) | Receiver が push した SET を 202 で受理した | info | 運用: Shared Signals |
audit.SSFPushRejected(ssf.push_rejected) | Receiver が push した SET に 400 を返した。再送せずに破棄する。Receiver がエラーコードを返したときは extras["err"] に入る | warn | 運用: Shared Signals |
audit.SSFPushRetried(ssf.push_retried) | push が一時的に失敗し(5xx、429、ネットワーク)、再送を予約した。extras は attempts と next_attempt_at | warn | 運用: Shared Signals |
audit.SSFPushAbandoned(ssf.push_abandoned) | 最後の再送でも届かず SET を破棄した、または stream の authorization header を復号できなくなった(extras["reason"] = "seal") | alert | 運用: Shared Signals |
audit.SSFPollSETError(ssf.poll_set_error) | poll の Receiver が処理できなかった SET を報告した(RFC 8936 の setErrs)。その SET は破棄する。extras は err と description | warn | 運用: Shared Signals |
安定性
監査イベント名は公開 API 表面の一部です:
- 新しいイベントは、マイナーリリースで追加され得ます。
- 既存のイベント名は、メジャーリリースで deprecation notice 付きでしか改名されません。
- godoc で Experimental と記されたイベント(
audit.TokenExchangeIDJAGIssuedとaudit.CIMD*)は、追跡している IETF ドラフトに従い、マイナーリリースで変わる場合があります。
ダッシュボードや SIEM ルールはイベント名で固定し、出現順序や、このページに記載のない extras フィールドの形には依存しないでください。
このリストの裏取り
git clone https://github.com/libraz/go-oidc-provider.git
cd go-oidc-provider
audit_catalog_tmp=$(mktemp ./audit-catalog-XXXXXX.go)
trap 'rm -f "$audit_catalog_tmp"' EXIT
cat >"$audit_catalog_tmp" <<'EOF'
package main
import (
"fmt"
"github.com/libraz/go-oidc-provider/op/audit"
)
func main() {
for _, def := range audit.Catalog() {
fmt.Println(def.Event)
}
}
EOF
go run "$audit_catalog_tmp"公開 API audit.Catalog() を呼び出し、このページがミラーしている閉じたカタログを出力します。