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

Registration responses and errors

The printing company's deployment pipeline has just sent the registration request for review site 482. A pipeline cannot read an error page or look around a console, so it has to understand what comes back: a new client and its credentials, a client that is not quite what it asked for, or a refusal with a reason.

A successful registration

All domains, identifiers, and secrets in these examples are fictional. When the photo service accepts a request, it answers with 201 Created:

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

{
  "client_id": "review-482-b17f",
  "client_secret": "demo-registered-secret-482",
  "client_id_issued_at": 1790845200,
  "client_secret_expires_at": 1793437200,
  "client_name": "Photo Printer review 482",
  "redirect_uris": ["https://review-482.test.printer.example/oauth/callback"],
  "grant_types": ["authorization_code"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "client_secret_basic",
  "scope": "photos.read"
}

client_id is the one member every successful response must contain. The server chose it, and it should not be in use by any other client.

client_secret appears because this client registered as a confidential client using client_secret_basic. A secret issued this way must be unique to this client ID. The phone installation in the earlier example received no secret, because it authenticates with its own key.

client_id_issued_at and client_secret_expires_at are times in seconds since 1 January 1970, like the timestamps in a JWT. This client was created at 2026-10-01 09:00 UTC, and its secret expires thirty days later, at 2026-10-31 09:00 UTC, because review sites are temporary. Whenever a secret is issued, the expiry must be present. A value of 0 means the secret does not expire.

The rest of the response lists the client's registered metadata, including values the server supplied itself. It is the record of what was registered, not an echo of what was asked for. If a registration used a software statement, the response returns the statement unchanged, and also lists the values the server took from it as ordinary members.

The response contains a secret, so it is marked no-store, and the pipeline writes the client ID and secret straight into its secrets store, never into its build log.

Checking what was registered

Compare the response with the request from Registering a client dynamically. The pipeline asked for the authorization_code and refresh_token grants and received only authorization_code, because the photo service does not issue refresh tokens to temporary review clients. The response also lists response_types, which the pipeline did not send, because the server filled in the value the authorization code grant implies.

A server may reject or replace any requested value, so a client has to read the response rather than assume its request was granted. The question is practical: can this client still do its job? Review site 482 can connect a test photo account and read photos, but it cannot test the yearly calendar's December refresh from The refresh token grant. The pipeline can accept that and run refresh tests elsewhere, or report the difference so a person can decide.

Some differences make a registration unusable. If the server had changed token_endpoint_auth_method to a method the software does not implement, or dropped the only redirect URI the site can receive, the client must not carry on as though its request had been granted. It reports the problem now rather than failing later in a way that looks unrelated.

The expiry is part of the result too. A client issued an expiring secret needs a plan for that date: register again, or update its registration where the server allows it, before client_secret_expires_at passes.

When registration fails

When the server refuses a request, it answers with 400 Bad Request and a JSON body containing an error code, and optionally an error_description for developers. This one went to a development build of the phone app that tried to register http://app.printer.example/oauth/callback:

HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store

{
  "error": "invalid_redirect_uri",
  "error_description": "Redirect URIs on remote hosts must use https."
}

RFC 7591 defines four error codes:

ErrorMeaning, with an example
invalid_redirect_uriOne or more redirect URIs are not acceptable, such as the plain HTTP address above.
invalid_client_metadataAnother field has a value the server will not accept, such as the authorization_code grant with a response type list that leaves out code. A server may substitute a suitable value instead of returning this error.
invalid_software_statementThe software statement is not valid, for example because it is malformed or its signature does not verify.
unapproved_software_statementThe statement may be valid, but it is not approved for use at this server, such as one signed by an issuer the photo service has not agreed to trust.

Problems with an initial access token are reported the way any API reports a bearer token problem, as Using access tokens described. A request without the token, or with one that has expired or been revoked, gets a 401 with a WWW-Authenticate challenge, which carries error="invalid_token" when a token was sent but is not valid.

None of these errors is cured by sending the same request again. The pipeline stops and reports the code. The phone app shows a short message and reports the failure to the printing company, rather than retrying in a loop until the server's rate limits block it. The error_description belongs in developers' logs, and like any text from another party it is untrusted: displayed as text, never inserted into a page as markup.

Some authorization servers include two more members in a successful response, registration_client_uri and registration_access_token, which let a client read, change, and delete its registration later. Dynamic registration management covers them.

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 2A registration response contains a client_secret and "client_secret_expires_at": 0. What does the 0 mean?

QUESTION 2 OF 2The pipeline asked for the authorization_code and refresh_token grants, and the response lists only authorization_code. What should it conclude?

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