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

Register a review-site client through the registration API

Act as the printer's deployment pipeline: register a client with an initial access token, compare open registration, and today create the same client in the portal to see what an API would replace.

PlannedUses your lab tenant

The lesson

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.

Request console

Requests in this lab can be sent from this page to your tenant: open one and choose Send. Fill in the values below first. They stay in this page's memory and are gone when you leave; secrets are never stored or sent anywhere except the request you send.

Setup

  1. Set the shell variables for your lab tenant (export ISSUER=...) and start btl-lab callback in a second terminal when a step signs in.

  2. Planned (G9): open OAuth > Registration and set the mode to Protected (proposed options Off, Protected, Open; default Off). Set the defaults for registered clients: consent mode always, a "Registered through the API" label on the consent screen, allowed scopes photos.read, and no refresh grant.

  3. Planned (G9): on the same screen, create an initial access token named review-pipeline, expiring in 7 days, with the constraint "redirect URIs must start with http://127.0.0.1:8765/". It is shown once, so read it without echoing: read -rs IAT; export IAT.

Planned walkthrough

  1. Find the endpoint in metadata.

GET$ISSUER/.well-known/oauth-authorization-server Open in console
GET $ISSUER/.well-known/oauth-authorization-server

registration_endpoint is $ISSUER/oauth/register.

Why it matters: "When a form is not enough". Software finds the endpoint in metadata, with no console visit.

  1. Register review site 482 as the pipeline would.

REG=$(curl -s "$ISSUER/oauth/register" -H "Authorization: Bearer $IAT" -H 'Content-Type: application/json' -d '{
  "client_name": "Photo Printer review 482",
  "redirect_uris": ["http://127.0.0.1:8765/review-482/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "token_endpoint_auth_method": "client_secret_basic",
  "scope": "photos.read"}')
jq 'del(.client_secret, .registration_access_token)' <<<"$REG"

The response stays in the shell variable REG, never in a file. Expect 201 with a tenant-chosen client_id, a client_secret and the registered metadata. The jq filter leaves the two credentials out of your screen.

Why it matters: "Sending a registration request". The body is JSON client metadata, and protected registration tells the tenant which token, and so which administrator, stands behind this client.

  1. Open OAuth > Clients. The new client is listed with its origin, "Registered with initial access token review-pipeline". Audit shows oauth.register succeeded with the token's creator as the accountable person.

Why it matters: registrations stay traceable to whoever issued the token, and revoking that token stops new registrations without touching existing clients.

  1. Run a code flow with the new client. The consent screen shows "Photo Printer review 482" with the "Registered through the API" label.

Why it matters: the tenant treats a self-described name with caution rather than as proof.

  1. Switch the mode to Open for this step only, and register an installation with no credential and token_endpoint_auth_method none. Each call returns a new client_id. With G56, an installation could instead send its public key by value in jwks and use private_key_jwt.

Restore: set the registration mode back to Protected.

Why it matters: "One client per installation". Each registration can be disabled alone, but nothing in it proves which software sent it.

Do today

  1. Call the registration endpoint.

curl -si "$ISSUER/oauth/register" -H 'Content-Type: application/json' -d '{"client_name":"x"}'

The answer is 501 temporarily_unavailable, and Logs show oauth.register rejected not_implemented.

  1. Read the metadata request from Planned walkthrough step 1 against your tenant. There is no registration_endpoint, and btl_endpoint_status["/oauth/register"] is "not_implemented".

  2. Do the pipeline's job by hand. In OAuth > Clients, create lab-tmp-review-482 with the Web application preset, using the step 2 values: redirect URI http://127.0.0.1:8765/review-482/callback, grants authorization_code and refresh_token, scope photos.read. Note which form fields map directly to RFC 7591 names (client_name, redirect_uris, grant_types, response_types, scope) and that the secret is shown once.

  3. Edit the client and try the redirect URI http://review-482.test.printer.example/callback. The portal refuses it, because a remote address must use HTTPS. A registration endpoint applies the same rule.

  4. Open Audit: tenant.oauth.clients.create names you as the actor. A console registration always has an authenticated, accountable person behind it. Imagine doing steps 3 and 5 several times a day for every review site, which is the case the lesson describes.

Break it

These run once G9 exists.

  1. Register with a redirect URI outside the token's constraint, http://127.0.0.1:9999/x. Expect 400 {"error":"invalid_redirect_uri"}.

  2. Revoke review-pipeline in the portal and register again. Expect 401 with WWW-Authenticate: Bearer error="invalid_token". The client from step 2 keeps working: it is a separate record.

Check your work

Today, Logs show oauth.register rejected not_implemented, and Audit shows tenant.oauth.clients.create and, after Cleanup, tenant.oauth.clients.delete for lab-tmp-review-482. Once G9 exists, Audit also shows oauth.register succeeded twice, the two Break it refusals, and the initial access token's creation and revocation.

Cleanup

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

  2. Once G9 exists, keep the registered review client and the REG variable (same shell) for the registration management labs, or delete the client; set the registration mode back to Off when you finish them.

Missing infrastructure

  • G9: the registration endpoint, a tenant registration policy (Off, Protected, Open, with Off as the default), initial access tokens with constraints and expiry, labelling of registered clients on the consent screen, attribution of each registration to its token's creator, and a registration rate limit registered as a visible tenant usage policy. Open mode must stay bounded per tenant.

  • G56: per-client public keys, so an installation can register a key by value and use private_key_jwt.

  • 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