# Update a client registration (RFC 7592)

`PUT /register/{client_id}`

Replaces the client's metadata. The body MUST contain the complete
metadata set (not a partial patch) and MUST NOT include server-issued
fields (registration_access_token, registration_client_uri,
client_id_issued_at, client_secret_expires_at).

## Authorization

- [Registration access token](https://www.nauthera.io/docs/v1/api#auth-registrationAccessToken) (`registrationAccessToken`)

Authorization header: 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.

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

## Path parameters

- `client_id` (string, required): The registered client identifier. Constraints: 1–256 characters; pattern `^[!-~]+$`.

## Request body (`application/json`)

Client metadata for dynamic registration (RFC 7591 §2, with OpenID Connect Dynamic Client Registration extensions).

- `client_id` (string, optional): RFC 7592 §2.2 requires an UPDATE (PUT) body to carry the client's own `client_id`, and the server MUST reject a value that differs from the currently issued one. On registration (POST) it is ignored: a client never influences its own identifier (RFC 9700 §4.15.1). Constraints: at most 256 characters.
- `client_secret` (string, optional): RFC 7592 §2.2: if present on an UPDATE it MUST match the currently issued secret; a client may never overwrite its secret with a value of its own choosing. Ignored on registration. Constraints: at most 512 characters.
- `redirect_uris` (array of strings (uri), optional): Redirection URIs (REQUIRED for redirect-based grants). Constraints: 1–32 items; no duplicates; each item: at most 2048 characters. Example: `["https://app.example.com/callback"]`.
- `token_endpoint_auth_method` (enum, optional): One of: `"none"`, `"client_secret_basic"`, `"client_secret_post"`, `"private_key_jwt"`, `"tls_client_auth"`, `"self_signed_tls_client_auth"`.
- `token_endpoint_auth_signing_alg` (enum, optional): One of: `"ES256"`, `"RS256"`.
- `grant_types` (array of strings, optional): Constraints: at most 16 items; no duplicates; each item: at most 128 characters. Example: `["authorization_code","refresh_token"]`.
- `response_types` (array of strings, optional): Constraints: at most 8 items; no duplicates; each item: at most 64 characters. Example: `["code"]`.
- `client_name` (string, optional): Constraints: at most 256 characters. Example: `"Example App"`.
- `client_uri` (string (uri), optional): Constraints: at most 2048 characters.
- `logo_uri` (string (uri), optional): Constraints: at most 2048 characters.
- `scope` (string, optional): Constraints: at most 2048 characters; pattern `^\S+( \S+)*$`. Example: `"openid profile email"`.
- `contacts` (array of strings (email), optional): Constraints: at most 32 items; no duplicates; each item: at most 256 characters.
- `tos_uri` (string (uri), optional): Constraints: at most 2048 characters.
- `policy_uri` (string (uri), optional): Constraints: at most 2048 characters.
- `jwks_uri` (string (uri), optional): Constraints: at most 2048 characters.
- `jwks` (object, optional): The client's public JWK Set, by value (RFC 7591 §2): the alternative to jwks_uri, and refused alongside it. It is held to the rules a fetched set obeys: a key with private members refuses the whole set, a key this server cannot verify with is ignored, and a set with no usable key is refused.
- `software_id` (string (uuid), optional)
- `software_version` (string, optional): Constraints: at most 128 characters.
- `software_statement` (string, optional): Constraints: at most 16384 characters.
- `application_type` (enum, optional): One of: `"web"`, `"native"`.
- `subject_type` (enum, optional): One of: `"public"`, `"pairwise"`.
- `sector_identifier_uri` (string (uri), optional): Constraints: at most 2048 characters.
- `id_token_signed_response_alg` (string, optional): Constraints: at most 16 characters.
- `userinfo_signed_response_alg` (string, optional): Constraints: at most 16 characters.
- `request_object_signing_alg` (string, optional): Constraints: at most 16 characters.
- `default_max_age` (integer, optional): Constraints: between 0 and 315360000.
- `require_auth_time` (boolean, optional)
- `default_acr_values` (array of strings, optional): Constraints: at most 16 items; no duplicates; each item: at most 256 characters.
- `initiate_login_uri` (string (uri), optional): Constraints: at most 2048 characters.
- `request_uris` (array of strings (uri), optional): Constraints: at most 8 items; no duplicates; each item: at most 2048 characters.
- `post_logout_redirect_uris` (array of strings (uri), optional): Constraints: at most 32 items; no duplicates; each item: at most 2048 characters.
- `backchannel_logout_uri` (string (uri), optional): Constraints: at most 2048 characters.
- `backchannel_logout_session_required` (boolean, optional)
- `frontchannel_logout_uri` (string (uri), optional): Constraints: at most 2048 characters.
- `frontchannel_logout_session_required` (boolean, optional)

## Responses

### 200 OK

The updated client registration.

Content type: `application/json`

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

Client information response (RFC 7591 §3.2.1 + RFC 7592). Echoes the registered metadata and adds the server-issued credentials and management fields.

- `client_id` (string, required): Example: `"nauthera_2Rk9"`.
- `client_secret` (string, optional): Present for confidential clients only.
- `client_id_issued_at` (integer, optional): Example: `1735686000`.
- `client_secret_expires_at` (integer, optional): Epoch seconds, or 0 if the secret never expires. Example: `0`.
- `registration_access_token` (string, optional): RFC 7592 token authorizing management of this registration.
- `registration_client_uri` (string (uri), optional): RFC 7592 management endpoint for this client. Example: `"https://auth.example.com/register/nauthera_2Rk9"`.
- `redirect_uris` (array of strings (uri), optional)
- `token_endpoint_auth_method` (string, optional)
- `token_endpoint_auth_signing_alg` (string, optional)
- `grant_types` (array of strings, optional)
- `response_types` (array of strings, optional)
- `client_name` (string, optional)
- `client_uri` (string (uri), optional)
- `logo_uri` (string (uri), optional)
- `scope` (string, optional)
- `contacts` (array of strings, optional)
- `tos_uri` (string (uri), optional)
- `policy_uri` (string (uri), optional)
- `jwks_uri` (string (uri), optional)
- `jwks` (object, optional): The client's public JWK Set, when it registered one by value.
- `software_id` (string, optional)
- `software_version` (string, optional)
- `application_type` (string, optional)
- `post_logout_redirect_uris` (array of strings (uri), optional)
- `request_uris` (array of strings (uri), optional)
- `id_token_signed_response_alg` (string, optional)
- `userinfo_signed_response_alg` (string, optional)
- `backchannel_logout_uri` (string (uri), optional)
- `backchannel_logout_session_required` (boolean, optional)
- `frontchannel_logout_uri` (string (uri), optional)
- `frontchannel_logout_session_required` (boolean, optional)

### 401 Unauthorized

Registration error (RFC 7591 §3.2.2).

Content type: `application/json`

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

A dynamic client registration error (RFC 7591 §3.2.2).

- `error` (enum, required): One of: `"invalid_redirect_uri"`, `"invalid_client_metadata"`, `"invalid_software_statement"`, `"unapproved_software_statement"`, `"invalid_token"`, `"access_denied"`, `"temporarily_unavailable"`.
- `error_description` (string, optional): Example: `"token_endpoint_auth_method is not supported"`.

### 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

Registration error (RFC 7591 §3.2.2).

Content type: `application/json`

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

A dynamic client registration error (RFC 7591 §3.2.2).

- `error` (enum, required): One of: `"invalid_redirect_uri"`, `"invalid_client_metadata"`, `"invalid_software_statement"`, `"unapproved_software_statement"`, `"invalid_token"`, `"access_denied"`, `"temporarily_unavailable"`.
- `error_description` (string, optional): Example: `"token_endpoint_auth_method is not supported"`.

## Example request

```bash
curl -g -X PUT 'https://auth.example.com/register/{client_id}' \
  -H "Authorization: Bearer $REGISTRATION_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "redirect_uris": [
      "https://app.example.com/callback"
    ],
    "token_endpoint_auth_method": "client_secret_basic",
    "grant_types": [
      "authorization_code",
      "refresh_token"
    ],
    "response_types": [
      "code"
    ],
    "client_name": "Example App",
    "scope": "openid profile email",
    "client_id": "{client_id}"
  }'
```

## Example response (200)

```json
{
  "client_id": "nauthera_2Rk9",
  "client_id_issued_at": 1735686000,
  "client_secret_expires_at": 0,
  "registration_client_uri": "https://auth.example.com/register/nauthera_2Rk9"
}
```
