# OAuth2 / OIDC authorization endpoint

`GET /authorize`

Starts the authorization-code flow (RFC 6749 §4.1, OIDC Core). PKCE is
required for public clients and enforced for all per RFC 9700; the
`code_challenge` is bound to the code and verified at the token endpoint.

On success redirects (302) to the client's exactly-registered
`redirect_uri` with `code`, `state`, and `iss` (RFC 9207). An error is
answered directly only while the client or its redirect URI is unknown
or invalid, and the server never redirects to an unvalidated URI; every
later error goes to the redirect URI with `error`, `state` and `iss`
(RFC 6749 §4.1.2.1).

Where the deployment serves the OpenID Connect implicit flow
(`response_types_supported` lists them), `id_token` and `id_token token`
return the ID token, and the access token, in the redirect's fragment
(OIDC Core §3.2). They require `nonce`, and are refused with
`unsupported_response_type` elsewhere.

Supports pushed authorization requests via `request_uri` (RFC 9126),
request objects via `request` / `request_uri` (RFC 9101 JAR), rich
authorization via `authorization_details` (RFC 9396), resource
indicators (RFC 8707), and DPoP key binding via `dpop_jkt` (RFC 9449).

## Authorization

None: this endpoint does not take API credentials.

This endpoint reads the browser session from the `Cookie` header: The request Cookie header; the interactive login / pending-auth session cookie, and the browser marker a sign-in is recognized by, are read from it.

This endpoint is rate limited; it answers `429` when a limit is hit.

## Query parameters

- `response_type` (string, optional): The response type. `code` for the authorization-code flow; `id_token` or `id_token token` for the implicit flow where it is served. Required unless the request arrives by `request_uri` (RFC 9126), in which case it comes from the pushed request. Constraints: at most 64 characters. Example: `"code"`.
- `client_id` (string, required): The registered client identifier (printable ASCII, no spaces). Constraints: 1–256 characters; pattern `^[!-~]+$`. Example: `"nauthera_2Rk9"`.
- `redirect_uri` (string (uri), optional): Must exactly match a registered redirect URI (RFC 9700 §2.1). Constraints: at most 2048 characters. Example: `"https://app.example.com/callback"`.
- `scope` (string, optional): Space-delimited scopes. `openid` requests an ID token. Constraints: at most 2048 characters; pattern `^\S+( \S+)*$`. Example: `"openid profile email"`.
- `state` (string, optional): Opaque CSRF value echoed back on the response. Constraints: at most 1024 characters. Example: `"af0ifjsldkj"`.
- `nonce` (string, optional): OIDC value bound into the ID token to mitigate replay. Constraints: at most 1024 characters. Example: `"n-0S6_WzA2Mj"`.
- `response_mode` (string, optional): How the authorization response is returned to the client: `query` for the code flow, `fragment` for the implicit flow. Any other value is refused with `invalid_request` on the redirect URI. Constraints: at most 64 characters. Example: `"query"`.
- `prompt` (string, optional): Space-delimited OIDC prompt values (none, login, consent, select_account). Constraints: at most 64 characters; pattern `^(none|login|consent|select_account)( (none|login|consent|select_account))*$`. Example: `"consent"`.
- `display` (enum, optional): One of: `"page"`, `"popup"`, `"touch"`, `"wap"`.
- `max_age` (integer, optional): Maximum authentication age in seconds (OIDC). Constraints: between 0 and 315360000. Example: `3600`.
- `login_hint` (string, optional): Constraints: at most 512 characters.
- `id_token_hint` (string, optional): A previously issued ID token hinting the current session. Constraints: at most 8192 characters.
- `ui_locales` (string, optional): Space-delimited BCP47 language tags for the UI. Constraints: at most 256 characters; pattern `^\S+( \S+)*$`. Example: `"en-US fr-CA"`.
- `acr_values` (string, optional): Space-delimited requested Authentication Context Class References. Constraints: at most 512 characters; pattern `^\S+( \S+)*$`.
- `claims` (string, optional): OIDC claims request (a JSON object, URL-encoded; OIDC Core §5.5). A claim its `userinfo` or `id_token` member names adds the scope that releases it, where the client is registered for that scope. Constraints: at most 8192 characters.
- `code_challenge` (string, optional): PKCE challenge (RFC 7636). base64url, required for public clients. Constraints: 43–128 characters; pattern `^[A-Za-z0-9_-]+$`. Example: `"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"`.
- `code_challenge_method` (string, optional): `S256`. Any other method, `plain` included (RFC 7636 §7.2, RFC 9700 §2.1.1), is refused with `invalid_request` on the redirect URI. Constraints: at most 64 characters. Example: `"S256"`.
- `request` (string, optional): A JWT-Secured Authorization Request object (RFC 9101 JAR). Constraints: at most 16384 characters.
- `request_uri` (string, optional): Reference to a pushed (RFC 9126) or hosted (RFC 9101) request object, e.g. urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14. Constraints: at most 2048 characters; pattern `^(urn:ietf:params:oauth:request_uri:|https://)\S+$`.
- `authorization_details` (string, optional): Rich Authorization Requests (RFC 9396), a JSON array (URL-encoded). Constraints: at most 8192 characters.
- `resource` (string (uri), optional): Resource indicator (RFC 8707) identifying the target resource server. Constraints: at most 2048 characters.
- `dpop_jkt` (string, optional): JWK SHA-256 thumbprint (base64url, 43 chars) binding the code to a DPoP key (RFC 9449). Constraints: exactly 43 characters; pattern `^[A-Za-z0-9_-]+$`.

## Headers

- `Cookie` (string, optional): The request Cookie header; the interactive login / pending-auth session cookie, and the browser marker a sign-in is recognized by, are read from it.

## Responses

### 302 Found

Redirect back to the client with an authorization code, OR to the
hosted login UI (/login) when no valid session exists. The
Location carries `code`, `state` (if supplied) and `iss` (RFC 9207)
on the success path, or the preserved authorization parameters on the
login path.

When the deployment serves OIDC Session Management 1.0 the success
Location additionally carries `session_state` (§3), the value the
relying party's iframe polls `check_session_iframe` with. It is absent
otherwise, and absent for a client whose redirect URI has no web
origin (a native custom scheme), which has nothing to compare against.

Headers:
- `Location` (string)
- `Cache-Control` = `no-store`
- `Pragma` = `no-cache`
- `Set-Cookie` (array of strings)

### 429 Too Many Requests

Too many requests.

Content type: `application/problem+json`

RFC 9457 (formerly RFC 7807) problem details (application/problem+json). `code` is a stable machine-readable slug for the problem kind (it mirrors the last path segment of `type`), so consumers can branch on it without parsing prose. `type` is `https://nauthera.io/problems/<code>`, which resolves to the code's runbook: why it happened, who is affected and what to do (RFC 9457 §3.1.1). A problem without a code has `about:blank`. `errors` is present on validation failures and lists every offending field.

- `title` (string, required): Example: `"Request validation failed"`.
- `status` (integer, required): Example: `400`.
- `type` (string (uri), optional): Example: `"https://nauthera.io/problems/validation_error"`.
- `detail` (string, optional): Example: `"One or more fields did not satisfy the API schema."`.
- `code` (enum, optional): The kind of problem, as a stable machine-readable slug a client branches on and translates rather than parsing `title` or `detail`, which are English prose for logs. A problem whose status says everything the server knows carries no `code`. One of: `"invalid_request"`, `"invalid_credentials"`, `"forbidden"`, `"unauthorized"`, `"insufficient_user_authentication"`, `"protected_account"`, `"password_held_by_directory"`, `"last_role_administrator"`, `"invalid_code"`, `"too_many_requests"`, `"too_many_attempts"`, `"account_locked"`, `"account_unavailable"`, `"already_enrolled"`, `"registration_disabled"`, `"registration_conflict"`, `"captcha_failed"`, `"invalid_reset_link"`, `"password_reused"`, `"password_too_short"`, `"password_too_long"`, `"password_compromised"`, `"invalid_verification_link"`, `"invalid_invitation_link"`, `"mail_relay_missing"`, `"email_unverified"`, `"not_found"`, `"conflict"`, `"unavailable"`, `"busy"`, `"window_too_large"`, `"too_many_series"`, `"internal_error"`, `"rate_limited"`, `"malformed"`, `"body_too_large"`, `"required"`, `"validation_error"`, `"unknown_org"`, `"invalid_token"`, `"invalid_dpop_proof"`, `"use_dpop_nonce"`, `"server_error"`.

  `validation_error` is the one code whose message is not a sentence about
  the code itself: the request failed the schema, and the specifics are
  the `errors` list — one entry per offending field — which a form renders
  on those fields. `required` and `malformed` are spelled like two of the
  per-field violation codes (`FieldError.code`) but mean something else;
  the two vocabularies are told apart by position, never by spelling.

  **Compatibility:** this is a CLOSED enum, with the same cost as
  `AuditAction`: a client generated against an older version of this
  document rejects a problem carrying a code added after it was built.
  Regenerate on upgrade, or decode the field as a plain string. It is
  enumerated anyway so that what a client must translate is knowable
  from the contract alone.
- `instance` (string, optional): Example: `"/introspect"`.
- `request_id` (string, optional): Example: `"8d94ed49-1caf-4ab3-9594-557142f2d023"`.
- `trace_id` (string, optional): Distributed-trace id (hex) for correlating this response with traces and logs. Present only when tracing is enabled and the request was recorded. Opaque and safe to log/share. Example: `"4bf92f3577b34da6a3ce929d0e0e4736"`.
- `errors` (array of objects, optional): Field-level violations (present for validation errors).

  Each item: A single field-level validation violation.
  - `field` (string, required): Offending field, dotted for nested bodies (e.g. child.id). Example: `"token_type_hint"`.
  - `code` (string, required): Machine-readable violation code: required, too_short, too_long, pattern, invalid_format, not_allowed, minimum, maximum, multiple_of, too_few, too_many, not_unique, malformed. Example: `"not_allowed"`.
  - `message` (string, required): Example: `"field token_type_hint must be one of [access_token, refresh_token]"`.

### Error

OAuth2 error response (RFC 6749 §5.2).

Content type: `application/json`

Headers:
- `Cache-Control` = `no-store`
- `WWW-Authenticate` (string)
- `DPoP-Nonce` (string)

An OAuth2 error response (RFC 6749 §5.2). `iss` (RFC 9207) is present on authorization-endpoint error responses so clients can detect mix-up.

- `error` (string, required): A single ASCII error code. Example: `"invalid_request"`.
- `error_description` (string, optional): Example: `"client_id, redirect_uri and response_type are required"`.
- `error_uri` (string (uri), optional): The error code's runbook (RFC 6749 §5.2): `https://nauthera.io/runbooks/oauth/<error>`. Example: `"https://nauthera.io/runbooks/oauth/invalid_request"`.
- `state` (string, optional): Echoed authorization-request state (RFC 6749 §4.1.2.1).
- `iss` (string (uri), optional): Issuer identifier on authorization error responses (RFC 9207).

## Example request

```bash
curl -G -i 'https://auth.example.com/authorize' \
  --data-urlencode 'response_type=code' \
  --data-urlencode 'client_id=nauthera_2Rk9' \
  --data-urlencode 'redirect_uri=https://app.example.com/callback' \
  --data-urlencode 'scope=openid profile email' \
  --data-urlencode 'state=af0ifjsldkj' \
  --data-urlencode 'nonce=n-0S6_WzA2Mj' \
  --data-urlencode 'response_mode=query' \
  --data-urlencode 'prompt=consent' \
  --data-urlencode 'max_age=3600' \
  --data-urlencode 'ui_locales=en-US fr-CA' \
  --data-urlencode 'code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM' \
  --data-urlencode 'code_challenge_method=S256'
```
