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

Hold a client to one authentication method

Read the tenant's supported methods, authenticate correctly, and see every other way of presenting a credential refused with the same uninformative answer.

Partly readyUses your lab tenant

The lesson

Builds on: Client credentials.

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

Partly ready. Most of this lab runs today. Steps that wait on platform features are marked, and Missing infrastructure says what they need.

Your progress

Press Start before you begin. Only events your tenant records after that count, in the order below. Checking reads your tenant's Audit, so you need Audit read access in it.

  1. Authenticate with the registered method

    Recorded as oauth.token succeeded for lab-print-orders.

  2. The right secret sent the wrong way is refused

    Recorded as oauth.token rejected (unsupported_auth_method) for lab-print-orders.

  3. A wrong secret is refused

    Recorded as oauth.token rejected (invalid_client) for lab-print-orders.

  4. A public client revokes with its client ID only

    Recorded as oauth.revoke succeeded (token_not_found) for lab-printer-app.

  5. A public client cannot use introspection

    Recorded as oauth.introspect rejected (client_authentication_required) for lab-printer-app.

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. In this lab CLIENT_ID and CLIENT_SECRET hold lab-print-orders, and APP_ID holds lab-printer-app. Define enc as in the earlier labs.

  2. Press Start on this page.

Walkthrough

  1. Read the methods the tenant supports at each back-channel endpoint.

curl -s "$ISSUER/.well-known/openid-configuration" | jq '{token_endpoint_auth_methods_supported, introspection_endpoint_auth_methods_supported, revocation_endpoint_auth_methods_supported}'

The answers are ["client_secret_basic","none"], ["client_secret_basic"] and ["client_secret_basic","none"].

Why it matters: client authentication happens only where a client talks directly to the authorization server. Each endpoint publishes which methods it accepts.

  1. Authenticate with the registered method, building the header the careful way: form-encode the client ID and secret, then join them with a colon and Base64-encode the result.

BASIC=$(printf '%s:%s' "$(enc "$CLIENT_ID")" "$(enc "$CLIENT_SECRET")" | openssl base64 -A)
curl -s -H "Authorization: Basic $BASIC" -d grant_type=client_credentials -d scope=prints.create "$ISSUER/oauth/token" | jq '{token_type, scope}'

The answer has a token. This tenant generates secrets from characters that need no escaping, so the form-encoding step changes nothing here, but a client that skips it fails as soon as a secret contains + or :.

  1. The right secret, sent the wrong way. Put it in the body, as a developer copying another provider's example might (client_secret_post).

curl -s -i -d grant_type=client_credentials -d scope=prints.create -d "client_id=$CLIENT_ID" -d "client_secret=$CLIENT_SECRET" "$ISSUER/oauth/token"

The answer is 401 invalid_client with "Confidential clients authenticate with HTTP Basic (client_secret_basic). Public clients send only client_id, with no secret." Audit records reason unsupported_auth_method.

Why it matters: the credential was correct, but the method was not the one this client uses. If a client could fall back to another method, any weaker credential the server still held would become a second way in.

  1. Both at once: add -u "$CLIENT_ID:$CLIENT_SECRET" to step 3. The answer is the same 401. One request uses one method; two are not doubly authenticated.

  1. A wrong secret, then an unknown client ID.

curl -s -i -u "$CLIENT_ID:wrong-secret-wrong-secret-wrong-secret" -d grant_type=client_credentials "$ISSUER/oauth/token"
curl -s -i -u "${CLIENT_ID%?}0:$CLIENT_SECRET" -d grant_type=client_credentials "$ISSUER/oauth/token"

Both answer 401 with the same body and WWW-Authenticate: Basic realm="OAuth token". If the last character of your client ID is already 0, use another digit in the second command.

Why it matters: the response does not say which part was wrong, so it does not help someone guessing at secrets. Audit records the wrong secret against lab-print-orders; the unknown client ID appears only as a count in Logs.

  1. A public client authenticates with none. Revoke a value that is not a token as lab-printer-app, identified by its client ID alone.

POST$ISSUER/oauth/revoke Open in console
POST $ISSUER/oauth/revoke HTTP/1.1
Content-Type: application/x-www-form-urlencoded

client_id=$APP_ID&token=not-a-token

The answer is 200 with {}. Send the same body to $ISSUER/oauth/introspect: 400 unauthorized_client, because introspection requires a client that can authenticate.

Planned walkthrough

These steps need a per-client authentication method setting with more methods (G8).

  1. Open OAuth > Clients > lab-print-orders and set Token endpoint authentication method to client_secret_post. Repeat step 3: 200. Repeat step 2: 401 invalid_client, now because Basic is not this client's method.

  2. Register a public key for lab-print-orders and switch it to private_key_jwt. A client assertion built by the lab toolkit from your own key is accepted, and both secret forms are refused. Audit records which method each request used.

Break it

Steps 3 to 6 are the deliberate failures. No setting changes.

Check your work

Press Check my progress. Logs also has an oauth.token rejected invalid_client summary with status 401 that includes the unknown client ID from step 5.

Cleanup

None.

Missing infrastructure

  • **G8, client authentication beyond client_secret_basic and none.** A per-client token_endpoint_auth_method setting with client_secret_post, client_secret_jwt, private_key_jwt (a registered JWK or jwks_uri) and tls_client_auth or self_signed_tls_client_auth, with Audit recording the method used. With it, the planned steps move lab-print-orders between methods and see each other method refused.

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