Send the authorization code to the client redirect with code + state + iss | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: POST /ui/consent arrives for a page this walk did not render
- Find the realm of the host: the request has its realm
- Count the request against the authorize limit: the address is under its limit
- Check the form against the consent form schema: the form matches the schema
- Find the browser session: the session is live
- Check the CSRF value against the session's: the values are equal
- Burn the CSRF value: the value is burned
- Find the client again: the client is enabled and not suspended
- Check the redirect URI against the client and its environment again: the redirect URI is registered and permitted
- Read the DPoP key from the form: dpop_jkt is absent, unread or well formed
- Read the decision: the user pressed Allow
- Refuse an agent scope above the client's cap, where the code is minted: no agent scope is above the cap
- Grant only the scopes the page showed: the posted scopes are the shown ones
- Grant only the resources the page named: the posted resources are the named ones
- Ask for a fresh sign-in when the grant needs one: the sign-in is fresh enough, and the approval is for this request only
- Mint the authorization code: the code is stored
- Record the grant: the events are recorded
|
Tell the client the user denied the request redirect, error=access_denied | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Deny, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: POST /ui/consent arrives for a page this walk did not render
- Find the realm of the host: the request has its realm
- Count the request against the authorize limit: the address is under its limit
- Check the form against the consent form schema: the form matches the schema
- Find the browser session: the session is live
- Check the CSRF value against the session's: the values are equal
- Burn the CSRF value: the value is burned
- Find the client again: the client is enabled and not suspended
- Check the redirect URI against the client and its environment again: the redirect URI is registered and permitted
- Read the DPoP key from the form: dpop_jkt is absent, unread or well formed
- Read the decision: the user pressed Deny; consent.denied is recorded
|
Tell the client an agent scope is above its cap redirect, error=invalid_scope | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, it names one (any agent:* scope for a client that is no agent or has no cap, or a mode above its cap), and an operator provisioned the client: the system client or the seed manifest, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address is under its limit
- Check the query against the authorize schema: the query matches the schema
- Find the browser session: the session is live
- Find the client: the client is enabled and not suspended
- Check the redirect URI against the client and its environment: the redirect URI is registered and permitted
- Read the DPoP key the code is to be bound to: dpop_jkt is absent, unread or well formed
- Refuse an agent scope above the client's cap: an agent scope is above the cap, for a client an operator provisioned
|
Show, rather than redirect, the agent-cap error of a client no operator provisioned no redirect, page shown | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, it names one, and the client registered itself: open registration, CIMD or a developer account, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address is under its limit
- Check the query against the authorize schema: the query matches the schema
- Find the browser session: the session is live
- Find the client: the client is enabled and not suspended
- Check the redirect URI against the client and its environment: the redirect URI is registered and permitted
- Read the DPoP key the code is to be bound to: dpop_jkt is absent, unread or well formed
- Refuse an agent scope above the client's cap: an agent scope is above the cap, for a client no operator provisioned
|
Refuse a scope set the page did not show redirect, error=invalid_scope | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scopes are another set, such as a tampered hidden field, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: POST /ui/consent arrives for a page this walk did not render
- Find the realm of the host: the request has its realm
- Count the request against the authorize limit: the address is under its limit
- Check the form against the consent form schema: the form matches the schema
- Find the browser session: the session is live
- Check the CSRF value against the session's: the values are equal
- Burn the CSRF value: the value is burned
- Find the client again: the client is enabled and not suspended
- Check the redirect URI against the client and its environment again: the redirect URI is registered and permitted
- Read the DPoP key from the form: dpop_jkt is absent, unread or well formed
- Read the decision: the user pressed Allow
- Refuse an agent scope above the client's cap, where the code is minted: no agent scope is above the cap
- Grant only the scopes the page showed: the posted scopes are not the ones the page showed; consent.denied is recorded
|
Refuse a resource set the page did not name redirect, error=invalid_target | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the scopes match, but the resource fields name other resources, or none where the page named some, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: POST /ui/consent arrives for a page this walk did not render
- Find the realm of the host: the request has its realm
- Count the request against the authorize limit: the address is under its limit
- Check the form against the consent form schema: the form matches the schema
- Find the browser session: the session is live
- Check the CSRF value against the session's: the values are equal
- Burn the CSRF value: the value is burned
- Find the client again: the client is enabled and not suspended
- Check the redirect URI against the client and its environment again: the redirect URI is registered and permitted
- Read the DPoP key from the form: dpop_jkt is absent, unread or well formed
- Read the decision: the user pressed Allow
- Refuse an agent scope above the client's cap, where the code is minted: no agent scope is above the cap
- Grant only the scopes the page showed: the posted scopes are the shown ones
- Grant only the resources the page named: the posted resources are not the ones the page named; consent.denied is recorded
|
Tell the client it named a QAuth API audience it does not list redirect, error=invalid_target | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, they name one, and an operator provisioned the client: the system client or the seed manifest, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address is under its limit
- Check the query against the authorize schema: the query matches the schema
- Find the browser session: the session is live
- Find the client: the client is enabled and not suspended
- Check the redirect URI against the client and its environment: the redirect URI is registered and permitted
- Read the DPoP key the code is to be bound to: dpop_jkt is absent, unread or well formed
- Refuse an agent scope above the client's cap: no agent scope is above the cap
- Describe the client from the server's own records: the client is described; the scopes to show are the requested ones the client's allowlist holds
- Refuse a QAuth API audience the client does not list: a resource names a QAuth API audience the client does not list, for a client an operator provisioned
|
Show, rather than redirect, the unlisted-audience error of a client no operator provisioned no redirect, page shown | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, they name one, and the client registered itself: open registration, CIMD or a developer account; an open registration or CIMD client lists none, whatever its row holds, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address is under its limit
- Check the query against the authorize schema: the query matches the schema
- Find the browser session: the session is live
- Find the client: the client is enabled and not suspended
- Check the redirect URI against the client and its environment: the redirect URI is registered and permitted
- Read the DPoP key the code is to be bound to: dpop_jkt is absent, unread or well formed
- Refuse an agent scope above the client's cap: no agent scope is above the cap
- Describe the client from the server's own records: the client is described; the scopes to show are the requested ones the client's allowlist holds
- Refuse a QAuth API audience the client does not list: a resource names a QAuth API audience the client does not list, for a client no operator provisioned
|
Send the browser to sign in, then back to the authorization request no redirect, page shown | The request carries no session cookie, or one that names a cookie key this process has not read yet and may not read again yet (#493), which is left for the next request, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address is under its limit
- Check the query against the authorize schema: the query matches the schema
- Find the browser session: the request carries no session; the authorize URL is rebuilt from the query
- Park the authorization request for the sign-in: the request is parked, for a request with no session
|
Clear the stale session cookie and send the browser to sign in no redirect, page shown | The cookie does not verify with the realm's cookie keys (#493), or it does but its session has ended or expired, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address is under its limit
- Check the query against the authorize schema: the query matches the schema
- Find the browser session: the cookie does not verify, or names a session that has ended, and is cleared
- Park the authorization request for the sign-in: the request is parked, for a stale cookie
|
End the session of a disabled or deleted user and send the browser to sign in no redirect, page shown | The session is live, but its user has been deleted or disabled, or was disabled after the session began and enabled again since, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address is under its limit
- Check the query against the authorize schema: the query matches the schema
- Find the browser session: the session's user is gone or disabled, or was disabled after the session began; the session is ended and its cookie cleared
- Park the authorization request for the sign-in: the request is parked, for a disabled user's session
|
Send the browser to sign in again before the grant no redirect, page shown | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, the form carries prompt=login, or the client's first-party profile is native_backend, whose request asks for a fresh sign-in as prompt=login does whatever the form says (ADR-017 Decision 9), and the sign-in is more than two minutes old, allow_forever is absent or any other value | - Wait for a consent request: POST /ui/consent arrives for a page this walk did not render
- Find the realm of the host: the request has its realm
- Count the request against the authorize limit: the address is under its limit
- Check the form against the consent form schema: the form matches the schema
- Find the browser session: the session is live
- Check the CSRF value against the session's: the values are equal
- Burn the CSRF value: the value is burned
- Find the client again: the client is enabled and not suspended
- Check the redirect URI against the client and its environment again: the redirect URI is registered and permitted
- Read the DPoP key from the form: dpop_jkt is absent, unread or well formed
- Read the decision: the user pressed Allow
- Refuse an agent scope above the client's cap, where the code is minted: no agent scope is above the cap
- Grant only the scopes the page showed: the posted scopes are the shown ones
- Grant only the resources the page named: the posted resources are the named ones
- Ask for a fresh sign-in when the grant needs one: the sign-in is too old for what is asked; step_up.required is recorded
- Park the authorization request for the sign-in: the request is parked, for a step-up
|
Refuse a request too large to park for the sign-in no redirect, page shown | The request carries no session cookie, or one that names a cookie key this process has not read yet and may not read again yet (#493), which is left for the next request, it is longer: the rebuild encodes each ~ ! ' ( ) of the parameters as three bytes, so a request line of some 8 KiB can give 24 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address is under its limit
- Check the query against the authorize schema: the query matches the schema
- Find the browser session: the request carries no session; the authorize URL is rebuilt from the query
- Park the authorization request for the sign-in: the rebuilt request is over 16 KiB
|
Refuse a form whose CSRF value is not the session's no redirect, page shown | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, it is another value, one an earlier POST of the session burned, or the session holds none; a form with no csrf_token fails the schema instead, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: POST /ui/consent arrives for a page this walk did not render
- Find the realm of the host: the request has its realm
- Count the request against the authorize limit: the address is under its limit
- Check the form against the consent form schema: the form matches the schema
- Find the browser session: the session is live
- Check the CSRF value against the session's: the posted value is not the session's live one
|
Refuse a client_id that names no client no redirect, page shown | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names no client of the realm, or a CIMD document that does not resolve, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address is under its limit
- Check the query against the authorize schema: the query matches the schema
- Find the browser session: the session is live
- Find the client: the client_id names no client of the realm
|
Refuse a client that is disabled or suspended no redirect, page shown | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a client that is disabled or suspended, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address is under its limit
- Check the query against the authorize schema: the query matches the schema
- Find the browser session: the session is live
- Find the client: the client is disabled or suspended
|
Refuse a redirect URI the client did not register no redirect, page shown | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, redirect_uri is none of the client's, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address is under its limit
- Check the query against the authorize schema: the query matches the schema
- Find the browser session: the session is live
- Find the client: the client is enabled and not suspended
- Check the redirect URI against the client and its environment: redirect_uri is not registered for the client
|
Refuse a registered redirect URI that no environment permits no redirect, page shown | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, redirect_uri is the client's, but no environment permits it: a scheme outside the allowed ones, or plain http to a host that is not loopback, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address is under its limit
- Check the query against the authorize schema: the query matches the schema
- Find the browser session: the session is live
- Find the client: the client is enabled and not suspended
- Check the redirect URI against the client and its environment: no environment permits that redirect_uri
|
Refuse a dpop_jkt that is not a key thumbprint no redirect, page shown | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, DPoP is on and dpop_jkt is not one thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address is under its limit
- Check the query against the authorize schema: the query matches the schema
- Find the browser session: the session is live
- Find the client: the client is enabled and not suspended
- Check the redirect URI against the client and its environment: the redirect URI is registered and permitted
- Read the DPoP key the code is to be bound to: dpop_jkt is not one thumbprint
|
Refuse a redirect URI the screen cannot show no redirect, page shown | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, every other parameter is valid, but the client display data (#593) cannot show where redirect_uri goes: an IPv6 address that is not loopback, a host that is not a DNS name of valid labels, or a scheme over 64 characters. Every registration path refuses such a URI since #593, so only an older client holds one; read by the GET only, after the agent cap, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address is under its limit
- Check the query against the authorize schema: the query matches the schema
- Find the browser session: the session is live
- Find the client: the client is enabled and not suspended
- Check the redirect URI against the client and its environment: the redirect URI is registered and permitted
- Read the DPoP key the code is to be bound to: dpop_jkt is absent, unread or well formed
- Refuse an agent scope above the client's cap: no agent scope is above the cap
- Describe the client from the server's own records: the client display data cannot show where the redirect URI goes
|
Refuse a query that does not match the authorize schema no redirect, page shown | The query (GET) or the form (POST) does not pass the route schema, such as a missing code_challenge or decision, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address is under its limit
- Check the query against the authorize schema: the query does not match the schema
|
Refuse a form that does not match the consent form schema no redirect, page shown | The query (GET) or the form (POST) does not pass the route schema, such as a missing code_challenge or decision, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: POST /ui/consent arrives for a page this walk did not render
- Find the realm of the host: the request has its realm
- Count the request against the authorize limit: the address is under its limit
- Check the form against the consent form schema: the form does not match the schema
|
Refuse a host that serves no browser route no redirect, page shown | The host names no realm, a disabled realm or a realm with no issuer, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the host names no enabled realm with an issuer
|
Refuse a GET over the global limit no redirect, page shown | The address has used up its requests for the window: the global limit for the GET, the authorize limit for the POST, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address has used up its requests
|
Refuse a POST over the authorize limit no redirect, page shown | The address has used up its requests for the window: the global limit for the GET, the authorize limit for the POST, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: POST /ui/consent arrives for a page this walk did not render
- Find the realm of the host: the request has its realm
- Count the request against the authorize limit: the address has used up its authorize requests
|
Fail on a session cookie that cannot be decoded no redirect, page shown | The request carries a session cookie whose value is not valid percent-encoding, such as %zz, which the cookie reader decodes without a catch, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: GET /ui/consent arrives, with the parameters of /oauth/authorize
- Find the realm of the host: the request has its realm
- Count the request against the global limit: the address is under its limit
- Check the query against the authorize schema: the query matches the schema
- Find the browser session: the session cookie cannot be decoded
|
Fail on a store error no redirect, page shown | The host is the primary host of an enabled realm, the address is under its limit, the query or form passes the route schema, and the request carries a live browser session of an enabled user, the authorization request, rebuilt for a sign-in redirect, is at most 16 KiB, client_id names a usable client, redirect_uri is one of its registered URIs that the environment permits, and dpop_jkt is absent, unread (DPoP off) or one base64url SHA-256 thumbprint, the scope parameter names no agent:* scope above the agent mode cap the operator set for the client, the resource indicators name no QAuth API audience (urn:qauth:aud:) that the client's own audience does not list, the client is not an agent: its is_agent is false, the client resolves to the production or staging profile, the posted csrf_token is the session's live value, the user pressed Allow, the posted scope, filtered by the client's allowlist, is the set the session bound for this client, and the posted resource fields name the bound resources, nothing asks for a fresh sign-in, or the sign-in is fresh enough for what asks, allow_forever is absent or any other value | - Wait for a consent request: POST /ui/consent arrives for a page this walk did not render
- Find the realm of the host: the request has its realm
- Count the request against the authorize limit: the address is under its limit
- Check the form against the consent form schema: the form matches the schema
- Find the browser session: the session is live
- Check the CSRF value against the session's: the values are equal
- Burn the CSRF value: it fails, because the cache fails
|