Beta

Create a tenant

A new tenant starts with its own users, OAuth settings, audit history and logs. You are its first Tenant Admin.

BTL Admin

Reading and updating a registration

Months after it registered, the Photo Printer installation on your phone is due to replace its signing key. Rotating client credentials described the safe order: register the new public key alongside the old one, switch to signing with the new key, then remove the old one. That lesson also noted that when a registration holds keys directly, rather than the address of a key set, adding and removing keys means updating the registration. For a developer with a console, that is a form. For an installation that registered itself, it has to be another API call.

The OAuth 2.0 Dynamic Client Registration Management Protocol, published as RFC 7592, defines one. It is an Experimental RFC, published to encourage implementation and gather experience rather than on the standards track, and not every server that supports dynamic registration implements it; many offer their own management interfaces instead. Its design still shows the questions any registration management interface has to answer.

The client configuration endpoint

All domains, identifiers, keys, and tokens in these examples are fictional. The photo service supports RFC 7592, so its registration responses include two members that the earlier examples left out. The installation's response began like this:

HTTP/1.1 201 Created
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
  "registration_client_uri": "https://auth.photos.example/register/app-7c41e2b9",
  "registration_access_token": "demo-registration-access-token-1",
  "client_id": "app-7c41e2b9",
  ...
}

registration_client_uri is the address of this client's client configuration endpoint, where the client reads and manages its own registration. The client uses the address exactly as given. Servers commonly build it from the registration endpoint and the client ID, as this one did, but a client must never construct it from those pieces itself.

registration_access_token is the credential that endpoint requires, sent as a bearer token on every call.

The endpoint uses the HTTP method to select the operation: GET reads the registration, PUT replaces it, and DELETE removes it. A server that does not support one of these methods must answer with an appropriate error.

Reading the current registration

GET /register/app-7c41e2b9 HTTP/1.1
Host: auth.photos.example
Accept: application/json
Authorization: Bearer demo-registration-access-token-1

The answer is 200 OK with the client's current registration, in the same format as the registration response. Current is meant literally. An administrator at the photo service may have narrowed the client's scope since it registered, or the server may have replaced a value. The installation learns what is actually registered, which may differ from what it remembers asking for.

The response may also contain a new client secret or a new registration access token. If it does, the client must discard the old one immediately and use the new one from then on. The client ID never changes.

Replacing the registration

To change anything, the client sends PUT with the complete registration. This is the part of the protocol that most often surprises developers: an update replaces the registration rather than merging changes into it. The request must contain every field as the server last returned it, and a field left out is treated as a request to remove it.

For the key rotation, the installation adds its new public key and sends everything else unchanged:

PUT /register/app-7c41e2b9 HTTP/1.1
Host: auth.photos.example
Content-Type: application/json
Accept: application/json
Authorization: Bearer demo-registration-access-token-1

{
  "client_id": "app-7c41e2b9",
  "client_name": "Photo Printer",
  "redirect_uris": ["https://app.printer.example/oauth/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "private_key_jwt",
  "jwks": {
    "keys": [
      { "kty": "EC", "crv": "P-256", "kid": "install-key-1", "x": "...", "y": "..." },
      { "kty": "EC", "crv": "P-256", "kid": "install-key-2", "x": "...", "y": "..." }
    ]
  },
  "scope": "photos.read"
}

A few rules shape the body. It must include client_id, matching the current one. It must not include registration_access_token, registration_client_uri, client_id_issued_at, or client_secret_expires_at, which belong to the server. A client that has a secret may include it, but only with its current value. A client can never choose its own secret.

Had the installation sent only client_id and the new jwks, the photo service would have treated every missing field as a request to remove it, and could have left a client with no redirect URI and no grants. The safe pattern is read, modify, write: fetch the current registration, change only what you mean to change, and send all of it back. RFC 7592 gives no way to detect that someone else changed the registration between that read and the write, so the last write wins.

A successful update returns 200 OK with the full registration, including any values the server replaced. Failures follow a short list:

ResponseMeaning
400A value is invalid and the server will not substitute one. The body uses the codes from Registration responses and errors, such as invalid_redirect_uri.
401The registration access token is not valid, or the client no longer exists.
403This client is not allowed to update its registration.

After the update succeeds, the installation signs its client assertions with install-key-2. Once the last assertion signed with the old key has expired, it reads the registration again and sends a second update without install-key-1.

Try it in the Lab

PUT IT INTO PRACTICE

Check your understanding

Try these questions before moving on. If an answer isn't right, use the feedback and try again.

0 of 2 answered correctly

Enable JavaScript to answer these questions and save progress in this browser.

QUESTION 1 OF 2An installation sends a PUT containing only its client_id and a new jwks. What may happen to its redirect URIs?

QUESTION 2 OF 2How should a client find its client configuration endpoint?

We value your privacy

We use cookies and similar technologies to enhance your browsing experience, and analytics to understand our traffic. By clicking "Allow All", you consent to optional analytics. Cookie Policy

Learn identity