# Pushed Authorization Request (RFC 9126)

`POST /par`

Accepts the authorization-request parameters directly from a
client-authenticated back channel and returns a single-use `request_uri`
the client then passes to `/authorize`. Hardens the flow against
request tampering and oversized front-channel requests. `request_uri`
MUST NOT be present in the PAR body.

## Authorization

- [HTTP Basic](https://www.nauthera.io/docs/v1/api#auth-clientSecretBasic) (`clientSecretBasic`)
- or no credentials (public clients)

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

## Headers

- `Authorization` (string, optional): The access token, as `Bearer <token>` (RFC 6750 §2.1) or, for a sender-constrained token, `DPoP <token>` (RFC 9449 §7.1). A token minted with a `cnf.jkt` confirmation is only accepted together with a `DPoP` proof signed by that key, whichever of the two schemes carries it.
- `DPoP` (string, optional): DPoP proof JWT (RFC 9449 §4). REQUIRED on a request presenting a DPoP-bound access token, and it must be signed by the key named in the token's `cnf.jkt` and cover this request's method and URI. The proof is read from the request itself rather than from this decoded parameter, so every protected operation is covered whether or not it declares it.

## Request body (`application/x-www-form-urlencoded`)

Authorization-request parameters pushed to the PAR endpoint (RFC 9126). Mirrors the /authorize query parameters plus client authentication.

- `request_uri` (string, optional): MUST NOT be sent; present only so the server can reject it. Constraints: at most 512 characters.
- `response_type` (string, optional): Constraints: at most 64 characters. Example: `"code"`.
- `max_age` (integer (int64), optional): Constraints: at least 0.
- `client_id` (string, optional): Constraints: 1–256 characters; pattern `^[!-~]+$`. Example: `"nauthera_2Rk9"`.
- `redirect_uri` (string (uri), optional): Constraints: at most 2048 characters. Example: `"https://app.example.com/callback"`.
- `scope` (string, optional): Constraints: at most 2048 characters; pattern `^\S+( \S+)*$`. Example: `"openid profile email"`.
- `state` (string, optional): Constraints: at most 1024 characters.
- `nonce` (string, optional): Constraints: at most 1024 characters.
- `response_mode` (string, optional): Constraints: at most 64 characters.
- `prompt` (string, optional): Constraints: at most 64 characters; pattern `^(none|login|consent|select_account)( (none|login|consent|select_account))*$`.
- `login_hint` (string, optional): Constraints: at most 512 characters.
- `ui_locales` (string, optional): Constraints: at most 256 characters; pattern `^\S+( \S+)*$`.
- `acr_values` (string, optional): Constraints: at most 512 characters; pattern `^\S+( \S+)*$`.
- `claims` (string, optional): Constraints: at most 8192 characters.
- `code_challenge` (string, optional): Constraints: 43–128 characters; pattern `^[A-Za-z0-9_-]+$`.
- `code_challenge_method` (string, optional): Constraints: at most 64 characters.
- `request` (string, optional): Constraints: at most 16384 characters.
- `authorization_details` (string, optional): Constraints: at most 8192 characters.
- `resource` (string (uri), optional): Constraints: at most 2048 characters.
- `dpop_jkt` (string, optional): Constraints: exactly 43 characters; pattern `^[A-Za-z0-9_-]+$`.
- `client_secret` (string, optional): Constraints: at most 512 characters.
- `client_assertion_type` (string, optional): Constraints: at most 128 characters. Example: `"urn:ietf:params:oauth:client-assertion-type:jwt-bearer"`.
- `client_assertion` (string, optional): Constraints: at most 16384 characters.

## Responses

### 201 Created

The pushed request was accepted.

Content type: `application/json`

Headers:
- `Cache-Control` = `no-store`

A pushed authorization request reference (RFC 9126 §2.2).

- `request_uri` (string, required): Single-use reference passed to /authorize. Example: `"urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c"`.
- `expires_in` (integer, required): Lifetime of the request_uri in seconds. Example: `90`.

### 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 -X POST 'https://auth.example.com/par' \
  --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'
```

## Example response (201)

```json
{
  "request_uri": "urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c",
  "expires_in": 90
}
```
