Skip to content

presented_jti names the token actually presented; agent passes presented_token to the PS (#152) - #153

Merged
dickhardt merged 8 commits into
mainfrom
presented-token
Sep 8, 2026
Merged

presented_jti names the token actually presented; agent passes presented_token to the PS (#152)#153
dickhardt merged 8 commits into
mainfrom
presented-token

Conversation

@dickhardt

@dickhardt dickhardt commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Addresses #152.

What changes

  • presented_jti names the token the request actually carried. Person token on the first challenge of a grant, auth token on a step-up or per-call challenge. The resource copies ps, sub, mission_s256, and tenant from whichever it verified and keeps no record. Resource Token Structure previously had the resource fill the value on a step-up from "its record of the person token it verified earlier," which it cannot key: an auth token carries no reference to the person token or the resource token, and (ps, sub, agent key) is the tuple §Why a Resource Token Names the Person Token already shows does not identify one person token.
  • Auth token request gains presented_token, REQUIRED. The agent passes the token it presented. It already holds it.
  • PS-to-AS request: person_token becomes presented_token, passed through. agent_token is unchanged; the AS still gets the AP's claims for policy.
  • One verification. Resource Token Verification step 6 now verifies presented_token by typ with the two substitutions the AS already applied (aud = resource token iss, cnf.jwk = agent_jkt), then checks jti = presented_jti and claims against the resource token. The AS section points at that step.
  • Retention narrows. The PS records jti, aud, exp, and any AS it presented to, for revocation, until exp plus skew. The lookup on the request path is gone.
  • Errors. unknown_person_token removed. invalid_presented_token added. expired_person_token and revoked_person_token renamed to expired_presented_token and revoked_presented_token, following the <parameter>_token pattern from Revocation: resource tokens, and what a revoked token gets back #150.
  • Expiry. An auth token is capped at the presented token's exp, whichever type. A step-up on a nearly expired auth token yields a nearly expired auth token; the existing early-refresh guidance is the way back to a full-length chain, and the refresh paragraph now says so.
  • Revocation. The AS records the presented_jti each auth token was issued against and follows its own records back to the person token on a step-up chain.
  • Rationale added to §Why a Resource Token Names the Person Token. Changelog entry added; the four earlier -11 entries this supersedes (Person token: the PS's retention obligation is implied but never stated #87, Rename person_token_jti — the credential it names is not always a person token #95, person_token in PS-to-AS, the revocation error names) are adjusted in place since -11 is unpublished.

Also in this PR

  • R3 resource token recital updated to match: presented_jti is the person token or, on a per-call challenge, the auth token.

Not in this PR

  • The login_endpoint flow (§Login) creates a resource token without a presented token. That was already inconsistent with the person-token-first rule and is untouched here.

🤖 Generated with Claude Code

https://claude.ai/code/session_017JbQcf8BB9PRyDoftadNjo

@dickhardt dickhardt added the protocol AAuth Protocol specification label Sep 8, 2026
dickhardt and others added 2 commits September 8, 2026 10:57
…ted_token to the PS (#152)

On a step-up or per-call challenge the request carries an auth token, and
Resource Token Structure had the resource fill presented_jti from a record
it cannot key. The resource now names the token it just verified, person
or auth. The auth token request gains presented_token, REQUIRED; the
PS-to-AS request's person_token becomes presented_token, passed through;
PS and AS run one verification. Retention narrows to what revocation
needs; unknown_person_token removed, invalid_presented_token added;
expired_/revoked_person_token renamed to _presented_token. Auth token exp
is capped at the presented token's exp.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017JbQcf8BB9PRyDoftadNjo
dickhardt and others added 6 commits September 8, 2026 13:28
…e agent refreshes at five minutes

A verifier judges exp against its own clock with no skew tolerance; iat
is not a validity check. The agent absorbs skew: it SHOULD refresh a
token with fewer than five minutes left and SHOULD NOT present one
inside that margin — a presented token is verified at several parties in
sequence, expiry propagates down the chain, and five minutes is the
resource token's maximum lifetime, so a token with that much left when a
resource token names it is still valid when the resource token is
redeemed. Refresh runs from the agent token down. Refresh is unnecessary
when the token will not be presented again; reactive renewal on
expired_jwt is acceptable for an auth token presented only to the
resource on an idempotent request.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEeAq61zr1oVg5FAFf3JTH
Never a reason to reject. Kept because neighbouring profiles (RFC 9068,
OpenID Connect Core) require it, it is the issuance time audit reports,
it gives a clock-free check of the issuer's lifetime ceiling (exp minus
iat), and a verifier MAY bound token age by its own policy. Each token
structure's iat line now points at the section.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEeAq61zr1oVg5FAFf3JTH
…st the five-minute margin

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEeAq61zr1oVg5FAFf3JTH
…ted window, not the refresh margin

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEeAq61zr1oVg5FAFf3JTH
…heck (match Expiry and the Refresh Margin)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEeAq61zr1oVg5FAFf3JTH
…fier's clock; wait, do not refresh

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEeAq61zr1oVg5FAFf3JTH
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

protocol AAuth Protocol specification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant