Add AuthZEN Access Request OAuth Profile (AROP) draft - #531
Conversation
New companion profile defining the OAuth token-issuance completion mode that the Access Request and Approval Profile (ARAP) defers to a downstream spec. A client requests a token (completion_mode=deferred, RAR authorization_details); the AS evaluates it as an AuthZEN Access Evaluation; on a denied-but-requestable decision it runs an ARAP access request and returns a Deferred Token Response (draft-gerber-oauth-deferred-token-response) with a deferral_code; the client polls the token endpoint; on approval the AS re-evaluates and issues an access token carrying the approved authorization, bounded by the approval expiry. Adds no new OAuth grant type or parameters: composes DTR (transport), RAR (requested and approved authorization), and ARAP (approval lifecycle). States the issuance-time authority shift honestly (decision at issuance, bounded by token lifetime) and keeps the decision behind the AS so the token carries the grant, not an AuthZEN decision object.
Restructures the profile so the asynchronous wait is pluggable across three OAuth mechanisms rather than hardwired to the Deferred Token Response. - Transport-neutral Common Processing core: resolution outcomes, continuation handle, polling/completion, idempotent submission, and access request input, defined once and shared by all bindings. - Three peer binding sections (Deferred Token Response, CIBA, OAuth Transaction Authorization Challenge) plus a per-transport comparison table. CIBA covers poll/ping/push delivery and self-approval; txn-challenge covers the resource-signed challenge flow. - PEP-placement axis as a deployment dimension: AS as PEP (DTR, CIBA), resource as PEP (txn-challenge), or both. Examples cover all three. - DTR example expanded into a full worked trace: AuthZEN Access Evaluation request/response and ARAP submission, task, and re-evaluation, each internal message marked off the OAuth wire. - evaluation_id vs binding_token denial-binding shown for co-located vs separate Access Request Service. - Adds CIBA (OIDC-CIBA Core 1.0) and txn-challenge references. Completion mode remains token issuance (not reevaluate); no new OAuth grant type, endpoint, or parameter of its own.
| - **Allow.** The transport's normal success response is returned synchronously (a token, for the request mechanisms that issue one directly). | ||
| - **Deny, not requestable.** A synchronous error is returned in the transport's error form: at the token endpoint, `invalid_authorization_details` ({{RFC9396}}) when the denial concerns the requested `authorization_details`, `invalid_scope` when it concerns requested `scope`, and otherwise `invalid_grant`. The pending and terminal-denial codes (`authorization_pending`, `access_denied`, `expired_token`, `slow_down`) are reserved for the deferred path and MUST NOT be returned here. | ||
| - **Deny, requestable.** The evaluating party MUST NOT issue a token. It submits an {{ARAP}} access request on the client's behalf, binds it to a continuation handle, and returns the transport's pending response (carrying the handle, `expires_in`, and `interval`). | ||
| - **Deny, requestable, but the client did not opt into asynchronous completion.** Where a binding requires the client to signal that it can handle a deferred outcome (DTR's `completion_mode=deferred`), and the client did not, the evaluating party MUST NOT defer. It returns the same synchronous denial error it would for a non-requestable denial; the requestable nature is not exposed. A client that wishes to obtain access through approval MUST opt in. |
There was a problem hiding this comment.
Why not provide client the requestable details so it can then opt in and use them for remediation?
There was a problem hiding this comment.
Are you asking about a shape similar to the following:
- The RS (as PEP) evaluates, gets a denied-but-requestable decision, and serializes it as your
insufficient_authorization/authorization_remediationchallenge (draft-zehavi-oauth-rar-metadata) carrying the requiredauthorization_details(and anauthorization_reference). - The client takes those
authorization_detailsto the AS in a fresh grant, opting into deferred completion (DTR) or via CIBA. - The AS runs the ARAP approval flow and, on approval, issues an access token whose granted
authorization_detailsfulfill the operation, audience-restricted to the RS. - The client re-presents the token; the RS matches it via
authorization_referenceand proceeds. Fulfillment is in the token.
So draft-zehavi-oauth-rar-metadata is the RS-initiated discovery/remediation front-end and AROP is the approval back-end, with the grant carried in the token. It reads as the unsigned, fresh-grant counterpart to the Transaction Authorization Challenge (signed, RS-as-PEP assertion): since authorization_remediation is not a signed requestable-denial assertion, the AS re-evaluates the request itself rather than consuming the RS's decision.
Does that match what you had in mind?
There was a problem hiding this comment.
Yes, that's what I had in mind.
Thanks for explaining it through my draft, serves incidentally as a review :-) so I appreciate any feedback it generates. One note - authorization_reference is returned by RS but never sent by the client to AS or RS. It's only usage is (using RAR to "scope" hashing logic) to help client locate an existing token in its possession that can remediate without requiring it to request a new grant.
But since AROP is an internal process between AS-as-PEP and a PDP, not exposed to the client, and since the AS never changes the grant chosen by the client, I still don't understand why is explicit opt-in required? Not as important but also why is DTR the opt in signal?
I can imagine a requestable denial requiring end-user approval only, which could be resolved without deferral.
Why not always return the denial with remediation options to the client to proceed with remediation as it sees fit?
Address PR review: a client engages exactly one binding and the evaluating party never converts a request made under one binding into another. The ARAP access request is an internal submission to the Access Request Service, not an outbound OAuth request; the continuation handle and pending response are always the same transport the request was made under. In the transaction challenge binding the client itself presents the challenge to the AS named in the challenge aud and authenticates there, so the originating deployment crosses no server-to-server credential.
… remediation Address PR review on the non-opt-in path: - Opt-in (DTR completion_mode=deferred) is a requirement of the deferral transport guarding the deferred response, not a precondition for approval; the internal access request and re-evaluation need no client opt-in. - Rather than silently deny, the evaluating party MAY surface a requestable denial as remediation, and the client proceeds as it sees fit: retry opting into DTR/CIBA, reuse an existing token, or pursue interactive end-user approval. A requestable denial does not by itself imply deferral. Disclosure stays deployment-policy-gated. - Add informative reference to draft-zehavi-oauth-rar-metadata as the resource-initiated discovery/remediation front-end that composes with this profile (what to request, transport carries the wait, token carries the fulfillment); the unsigned counterpart to the signed Transaction Authorization Challenge.
Address PR review on standing vs single-use access: - Recast the Authority-model design goal from a one-way tradeoff into two first-class completion modes a deployment chooses per approval: re-evaluation completion (ARAP reevaluate, per-call currency, no long-lived credential) and token-issuance completion (this profile, grant carried in the token, issuance-time decision bounded by lifetime). Reworded the adjacent goal to 'Shared completion semantics, several transports' to avoid a model/mode clash. - Rework the Approved refresh guidance: keep the invariant (no access token, refresh token, or exchanged token outlives approved_until or broadens the grant); under token-issuance completion, standing time-bounded approvals (path read, policy-granted privileges as RAR) are served by a refresh bounded by approved_until and re-evaluated at each refresh; single-use approvals (single payment, single-use Transaction Authorization Challenge) get none; per-call currency is re-evaluation completion, out of scope.
ogazitt
left a comment
There was a problem hiding this comment.
I've reviewed the spec and agree that it is a great way to map the "abstract" ARAP requestable denial protocol to OAuth token issuance flows, via the currently available and actively worked-on asynchronous token issuance mechanisms (DTR, CIBA, TX auth challenge).
I believe section 8.2 could potentially point back to a more definitive AuthZEN SARC mapping for token issuance scenarios.
I'm also not sure why AROP depends on OAuth RAR - my guess is that this is because a Client that uses a RAR request is a signal that it is already "tuned in" to a richer/finer-grained authz model, and therefore more likely to support the deferred token issuance workflow?
In my read, AROP doesn't need to constrain itself to RAR requests, and if it didn't, it could be more generally applicable to a broader set of OAuth token issuance scenarios.
|
|
||
| In every placement the access request, approval, and issuance-time re-evaluation are the same; only the origin of the requestable denial differs. | ||
|
|
||
| ## Constructing the Access Evaluation |
There was a problem hiding this comment.
I think we (i.e. the OAuth/AuthZEN ecosystem) are missing some connective tissue that more precisely defines the OAuth token issuance -> AuthZEN SARC information model mapping. I have some ideas here that are complementary to AROP.
…ge re-POST Make the AROP Transaction Challenge flow use the spec's continuation handle (openid/authzen#531) instead of re-POSTing the whole challenge each poll. The client presents the challenge ONCE; the AS mints an opaque transaction_authorization_id bound to the validated challenge AND the requesting client's cnf, and the client polls by that handle. Settles two conformance points raised in review: the flow is client-driven Transaction Challenge (not a DTR conflation, no RS-as-requester), and the handle is the AS-side binding token that captures the validated challenge state (D37: the AS owns the txn pending id). - provider.ts handleTransaction: branch on body shape after shared base-token+ DPoP auth. Initiation { challenge } -> validate + D42 subset-gate + openForTxn -> mint transaction_authorization_id, store { taskId, txn, missionId, cnfJkt, parameter_digest, authorizationDetails, subject, audience, expiresAt } -> 200 { transaction_authorization_id, expires_in, interval }. Poll { transaction_authorization_id } -> look up handle, verify base token cnf.jkt == stored cnf (handle bound to client), check the ARS task -> pending, or issue the txn-token from stored state (active mission unchanged, D42). Unknown id -> 404; cnf mismatch -> 403. - txn-endpoint.test.ts: rewritten to the handle flow (initiate -> pending -> approve -> poll-by-id -> token, all claim assertions preserved) + 404-unknown and 403-cnf-mismatch negatives. - exhibit.ts / server.ts: present the challenge once, poll by transaction_authorization_id; re-present the issued txn-token to the RS. RS side, crypto, and the txn-token shape are unchanged. Gate: typecheck clean, 128 tests (126 + 2 negatives), exhibit green (challenge once -> handle -> poll -> token -> PERMIT), browser + traces + evals + vendor-test pass.
|
Will hold the vote for this next week (27th Aug) |
Summary
Adds a new draft, the AuthZEN Access Request OAuth Profile (AROP), a companion to the AuthZEN Access Request and Approval Profile (ARAP).
ARAP defines a single completion mode (
reevaluate) and explicitly leaves completion modes that bind approval to a specific issuance flow, such as OAuth token issuance where the issued token is the decision representation, to a downstream profile. AROP is that downstream profile for OAuth.When a request is evaluated as an AuthZEN Access Evaluation and the decision is denied but requestable, AROP resolves the denial through an ARAP access request and completes by issuing an access token that carries the approved authorization. The completion semantics are the same regardless of how the asynchronous wait is carried; what varies is the OAuth mechanism.
Three transport bindings
The async wait is pluggable. AROP defines a transport-neutral processing core and three peer bindings:
draft-gerber-oauth-deferred-token-response): the client makes a token request, the AS returns adeferral_code, and the client polls the token endpoint.auth_req_id, and the principal approves out of band on a decoupled device (poll/ping redeem at the token endpoint; push delivers directly).draft-rosomakho-oauth-txn-challenge): a protected resource returns a signed challenge for an operation the presented token cannot authorize; the client takes it to the AS, which issues atxn-bound token re-presented to the resource.PEP placement
The bindings differ in where the requestable denial originates, and AROP accommodates all three ARAP deployments: AS as PEP (DTR, CIBA), resource as PEP (transaction challenge, where the resource signs the challenge), and both (the resource asserts the challenge and the AS also applies its own policy). The examples cover all three.
Design
draft-brossard-oauth-rar-authzen, noted in the draft.)reevaluate.evaluation_idvs PDP-signedbinding_tokendenial-binding for co-located vs separate Access Request Service.Notes
Makefile; the draft builds clean (kramdown-rfc -> xml2rfc) with all references resolving.authorization_details-typemapping to AuthZEN resource/action is deployment- or vocabulary-defined, and partial issuance across multipleauthorization_detailsis out of scope.