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

OAUTH 2.0 · LAB

Read what was really registered and handle each registration error

Compare a registration response with its request field by field, plan for a secret that expires, and trigger each RFC 7591 error. Today, compare the portal's secret handling and validation.

PlannedUses your lab tenant

The lesson

Builds on: Registering a client dynamically.

New to the labs? Start with the lab toolkit and the shared cast and names every lab uses.

Planned. The core of this lab waits on platform features that are not built yet. The planned walkthrough shows exactly how it will run; Do today is a real exercise you can do now.

Setup

  1. Keep the shell variables and, once G9 exists, the IAT token and the REG response from Register a review-site client through the registration API.

  2. Planned (G9): in OAuth > Registration, set the client secret lifetime for registered clients to 30 days and keep the refresh grant off for registered clients.

Planned walkthrough

  1. Compare what you asked for with what was registered.

diff <(jq -S '{grant_types, response_types, scope}' <<<"$REG") \
     <(echo '{"grant_types":["authorization_code","refresh_token"],"scope":"photos.read"}' | jq -S .)

refresh_token was dropped and response_types: ["code"] was added.

Why it matters: "Checking what was registered". The response is the record of what was registered, not an echo of the request.

  1. Read the two timestamps.

for t in client_id_issued_at client_secret_expires_at; do date -u -d @"$(jq -r .$t <<<"$REG")"; done   # macOS: date -u -r

They are thirty days apart.

Why it matters: "A successful registration". An expiring secret needs a plan before that date: register again, or update the registration where the tenant allows it.

  1. Decide whether the client can still do its job: it can sign in and read photos, but cannot refresh. Write that decision in your pipeline notes, or report it for a person to decide.

Why it matters: a client must read the response and act on differences, rather than fail later in a way that looks unrelated.

Do today

  1. In OAuth > Clients, create lab-tmp-review-482 with the Web application preset: redirect URI http://127.0.0.1:8765/review-482/callback, scope photos.read. Note what you receive: the client ID, and the secret shown once. There is no expiry; tenant secrets last until rotated. Store the secret: read -rs REVIEW_SECRET; export REVIEW_SECRET REVIEW_ID=<its client_id>.

  2. Make sure the client works, then rotate its secret in the portal and try the old one.

curl -s -u "$REVIEW_ID:$REVIEW_SECRET" "$ISSUER/oauth/token" -d grant_type=refresh_token -d refresh_token=demo | jq .error

Before rotating, the answer is invalid_grant (or unauthorized_client if the client lacks the refresh grant): either way the client authenticated, and only the request was wrong. After rotating, the same command gives invalid_client, and Audit shows oauth.token rejected invalid_client. The old secret stopped at once, with no warning date. Compare that with an expiry announced in a registration response.

  1. Trigger the portal's own validation and compare each message with the RFC 7591 codes:

    • The redirect URI http://review-482.test.printer.example/cb: refused, because a remote address must use HTTPS. A registration endpoint would answer invalid_redirect_uri.

    • A redirect URI with a fragment, such as http://127.0.0.1:8765/cb#x: refused. Same code.

    • A redirect URI whose query uses a response parameter name, such as http://127.0.0.1:8765/cb?code=1: refused. Same code.

    • A grant the Flow policy does not allow: the portal says to allow it in Flow policy first. A registration endpoint would answer invalid_client_metadata or substitute a value.

  2. Write down which of the four RFC 7591 codes the portal has no equivalent for: the two software statement errors, because the portal has no statements.

Break it

These run once G9 exists. Each refusal is a 400 with an error code, except the last.

  1. redirect_uris: ["http://review-482.test.printer.example/cb"]: invalid_redirect_uri.

  2. grant_types: ["authorization_code"] with response_types: ["token"]: invalid_client_metadata.

  3. software_statement: "not-a-jwt": invalid_software_statement.

  4. No Authorization header in Protected mode: 401 with a WWW-Authenticate: Bearer challenge.

None of these is cured by sending the same request again. Stop and report the code.

Check your work

Today, Audit shows tenant.oauth.clients.create, tenant.oauth.credentials.rotate and oauth.token rejected invalid_client for lab-tmp-review-482. Once G9 exists, Audit also shows oauth.register refusals with each error code as the reason.

Cleanup

  1. Delete lab-tmp-review-482 in OAuth > Clients and unset REVIEW_SECRET.

  2. Once G9 exists, delete the registered review client or keep it for the registration management labs.

Missing infrastructure

  • G9: the registration endpoint and its error responses, and secret expiry for registered clients.

  • G10: a rotation overlap window, so a pipeline can renew a secret before client_secret_expires_at without downtime.

  • Once these exist, the Planned walkthrough runs as written.

Back to all labs

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

The Lab