Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/claims-contract.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ RFC 9068 JWT access token。provider は `generateToken`(auth.provider の `pa
| `iss` | デプロイ設定の issuer。必須、リクエスト由来にしない。 | jose 検証でピン — `oauth.jwt.issuer` / `OAUTH_JWT_ISSUER`。 | デプロイの identity。 |
| `typ`(header) | access token は `at+jwt`(RFC 9068)、refresh token は `rt+jwt`、ID token(wire 名 `id_token`)は auth.provider v0.10.0 以降は標準の `JWT`(それ以前は非標準の `id+jwt` で、`typ` を厳格に検証する外部 RP に弾かれていた)。auth.provider#402(2026-08-30)で移行期間は終了し、現在は `JWT` のみを受理する。 | `oauth.jwt.tokenType`、default `at+jwt`。比較時に `application/` prefix は無視。 | 3 種の token を区別する **唯一の** 判別子 — このピンが、同じ鍵で署名された refresh / id token が `/verify` を通ることを防いでいる。防いでいる実体は **`at+jwt` と互いに素であること** であり、`JWT` は `id+jwt` と同様にこれを満たす。claim レベルの代替チェックは存在しない。 |
| `exp` / `iat` | 常に刻印(`core/src/grants/token.mts`)。 | 両方必須(`tokenAuthenticator` の必須 claim チェック + 常設の `maxTokenAgeSeconds` 上限)。`exp` のない token は永続 credential として拒否。 | 寿命。verifier は issuer の規律を信頼せず、issuer の `exp` をさらに上限で抑える。 |
| `amr` / `acr` | ユーザーがどう認証したか、どの保証レベルを満たしたか([auth.provider#481](https://github.com/o3co/auth.provider/issues/481))。`amr` はセッションが記録した RFC 8176 のメソッド列 — パスキーなら `["hwk"]` — で、`authorization_code`・`session`・WebAuthn の各 grant が刻印する。`acr` は `/authorize` が `acr_values` から満たした値で、`authorization_code` だけが刻印する。どちらも refresh token に載り、refresh は再認証ではないので、refresh が発行するすべての token に引き継がれる(`oauth/src/grants/refreshToken.mts`)。刻印されるのは形の正しい値だけ: `amr` は空でない文字列の空でない配列、`acr` は空でない文字列(`core/src/grants/authenticationClaims.mts`)。それ以外は省かれ、空で送られることはない。 | 組み込み collector は読まない。これらでゲートするデプロイは、検証済み claim から自前の attribute キーへの `PayloadClaimAttributeCollector` マッピング(`packages/builtins`)を宣言し、Rule を書く。 | **元の**認証イベント。`auth_time` と同じ(OIDC Core §12.2)— refresh された access token が示すのは、それが連なるログインであって refresh ではない。無いことは provider が何も記録しなかったことを意味し、ユーザーが第二要素を使わなかったという表明ではない。 |

## 境界を越えない claim

Expand Down
1 change: 1 addition & 0 deletions docs/claims-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Path convention for the tables below: paths in the *Provider writes* column are
| `iss` | Deployment-configured issuer; required, never request-derived. | Pinned by jose verification — `oauth.jwt.issuer` / `OAUTH_JWT_ISSUER`. | Deployment identity. |
| `typ` (header) | `at+jwt` on access tokens (RFC 9068), `rt+jwt` on refresh tokens, and the standard `JWT` on ID tokens (wire name `id_token`) since auth.provider v0.10.0 — it was the nonstandard `id+jwt` before, which strict external RPs rejected; auth.provider#402 (2026-08-30) closed the dual-accept window, so only `JWT` is accepted now. | `oauth.jwt.tokenType`, default `at+jwt`; an `application/` prefix on either side is ignored when comparing. | The **only** discriminator between the three token kinds — the pin is what keeps a refresh or id token signed with the same key from passing `/verify`. What does the keeping-out is being **disjoint from `at+jwt`**, which `JWT` satisfies exactly as `id+jwt` did. There is no claim-level fallback check. |
| `exp` / `iat` | Always stamped (`core/src/grants/token.mts`). | Both required (`tokenAuthenticator`'s required-claims check + the always-set `maxTokenAgeSeconds` bound); a token without `exp` is refused as a permanent credential. | Lifetime. The verifier additionally caps the issuer's `exp` rather than trusting issuer discipline. |
| `amr` / `acr` | How, and to which assurance level, the user authenticated ([auth.provider#481](https://github.com/o3co/auth.provider/issues/481)). `amr` is the RFC 8176 method list the session recorded — `["hwk"]` for a passkey — stamped by the `authorization_code`, `session` and WebAuthn grants; `acr` is the value `/authorize` satisfied from `acr_values`, stamped by `authorization_code` only. Both travel on the refresh token and are carried onto every token a refresh mints, since a refresh does not re-authenticate (`oauth/src/grants/refreshToken.mts`). Only well-formed values are stamped: `amr` a non-empty array of non-empty strings, `acr` a non-empty string (`core/src/grants/authenticationClaims.mts`); anything else is omitted, never sent empty. | No built-in collector reads them. A deployment that gates on them declares a `PayloadClaimAttributeCollector` mapping (`packages/builtins`) from the verified claim to an attribute key of its own, and writes the rule. | The **original** authentication event, as `auth_time` is (OIDC Core §12.2) — a refreshed access token reports the login it descends from, not the refresh. Absent means the provider recorded none; it is not a statement that the user did not use a second factor. |

## Claims that do NOT cross

Expand Down
Loading