Client registration in your tenant
A deployment pipeline that creates a client for every installation should not need a person at a console. Dynamic client registration (RFC 7591) lets software send its client metadata to your tenant and receive a client ID, and registration management (RFC 7592) lets it read, replace or delete that client later.
The same controls apply to BTL's own organization under BTL Admin, OAuth Management, Registration, which may use Off or Protected registration but not Open.
Registration policy
Open OAuth Management, Registration. Registration is Off by default: the endpoint refuses every request and discovery does not list it. Protected requires an initial access token. Open lets any software register, limited per network and by your tenant's client capacity, so nothing in an Open registration proves which software sent it.
The policy also decides what a registered client may receive: its grants (authorization code, refresh token, client credentials and device authorization), its client authentication methods, and which of your exclusive scopes it may ask for. Common scopes such as openid are available to every client. SCIM and authorization engine scopes are never offered, and the implicit, JWT bearer and token exchange grants stay with clients an administrator creates. Registered clients always use the code flow with PKCE, never skip consent, and need an administrator's approval when your Flow Policy allows only approved applications.
Values the policy does not allow are left out by default, and the response shows what was actually registered. Choose Refuse the registration to answer invalid_client_metadata instead. A client authentication method the policy does not allow is always refused, since a different method would leave the client unable to authenticate. Require links to share a host with the redirect URIs refuses a client_uri, logo_uri, policy_uri or tos_uri on another host.
Initial access tokens
Create a token under Initial access tokens with a name and an expiry of 1 to 90 days. It is shown once and stored only as a hash. It can require every redirect URI to start with a prefix, such as http://127.0.0.1:8765/review-482/: the scheme, host and port must match exactly, and the path must continue the prefix's path, without encoded slashes or dots. For a loopback prefix, include the port the pipeline registers with; at sign-in a registered loopback address still works on any port, as native applications need (RFC 8252). It can also allow a number of registrations. The person who creates a token is recorded as accountable for every client registered with it. Revoking a token stops new registrations; clients already registered with it keep working.
Registering a client
Discovery lists registration_endpoint while registration is on. Send the metadata as JSON:
POST /oauth/register HTTP/1.1
Authorization: Bearer $IAT
Content-Type: application/json
{"client_name": "Photo Printer review 482",
"redirect_uris": ["http://127.0.0.1:8765/review-482/callback"],
"grant_types": ["authorization_code"],
"token_endpoint_auth_method": "client_secret_basic",
"scope": "openid photos.read"}The answer is 201 with the registered metadata, a client_id, a client_secret for the secret methods, client_id_issued_at, client_secret_expires_at (0 when it does not expire), a registration_access_token and a registration_client_uri. The metadata goes through the same checks as the client editor, including redirect URI rules, authentication levels, pushed requests, DPoP and the FAPI 2.0 profile. A client using private_key_jwt sends jwks or a jwks_uri. While your Flow Policy offers mutual TLS, a client can register tls_client_auth with exactly one of tls_client_auth_subject_dn, tls_client_auth_san_dns, tls_client_auth_san_uri, tls_client_auth_san_ip or tls_client_auth_san_email, or self_signed_tls_client_auth with its certificate as x5c in its keys, and can ask for tls_client_certificate_bound_access_tokens; a certificate value sent for another method, or certificate settings while mutual TLS is off, are refused rather than ignored. A client gets the query response mode unless it sends response_modes, which are held to your Flow Policy like other values. A client that sends authorization_signed_response_alg or authorization_encrypted_response_alg also gets the JWT response modes (JARM) your Flow Policy allows, and is refused when it allows none. OpenID Connect logout addresses are registered too: post_logout_redirect_uris, frontchannel_logout_uri with frontchannel_logout_session_required, and backchannel_logout_uri with backchannel_logout_session_required, under the same rules as the client's Signing out settings (see Signing out). So are an initiate_login_uri, an id_token_signed_response_alg (RS256 when left out, except under your tenant's FAPI 2.0 profile, where the ID token manager's key applies), a userinfo_signed_response_alg and encrypted responses (id_token_encrypted_response_alg, userinfo_encrypted_response_alg, authorization_encrypted_response_alg, each with its _enc), under the same rules as the client screen: encryption needs a key marked for encryption in the jwks sent with it (see Signed and encrypted messages). Whether the client appears on people's Applications page stays your choice, not the client's; because an update replaces every setting, a client's own update turns that listing off until you turn it on again. Unknown metadata is ignored. sector_identifier_uri is not supported and is refused. The response's scope lists every scope the client can use: the exclusive scopes it received and your tenant's common scopes.
Errors are invalid_client_metadata, invalid_redirect_uri, invalid_software_statement and unapproved_software_statement with HTTP 400, invalid_token with HTTP 401 and a WWW-Authenticate header, access_denied with 403 while registration is off or the tenant is at its client capacity, and temporarily_unavailable with 429 when a limit is reached. The Clients list marks each registered client and says how it registered, and the consent page tells people it described itself.
Software statements
A software statement is a JWT in which a publisher vouches for its software's metadata (RFC 7591 section 2.3). Add the publisher under Software statement issuers with its iss value and the public keys it signs statements with. A registration that carries software_statement from a trusted, enabled issuer uses the statement's values wherever they disagree with the rest of the request, and records its software_id and software_version. A client registered with a statement must send one with every update, so the values the publisher vouched for cannot be replaced without it. A statement from an unknown issuer is unapproved_software_statement; a bad signature, a future iat or a past exp is invalid_software_statement. Require a software statement refuses registrations without one. The lab toolkit's btl-lab sign signs a statement with your own key.
Managing a registration
The client calls its registration_client_uri with its registration access token as a bearer token. GET returns the current registration. PUT replaces it with a full body that repeats client_id and leaves out the four fields the server owns; a field left out returns to its registration default, so send everything the read returned. A replacement also resets what an administrator set beyond registration metadata, such as approval for the app approval policy; changing redirect URIs or other access ends the client's tokens and remembered consent, as an edit in the portal does. DELETE answers 204 and ends the client, its secret and its registration access token together. You can turn updates and deletion off for registered clients.
Every response carries a new registration access token. The token used keeps working until the new one is first used, so a client that loses a response can still try again. A token works for one client only, and an unknown client and a wrong token look the same. Registrations made while registration was on stay manageable after you turn it off.
Secrets and cleanup
Secret lifetime sets how long a registered client's secret works, 0 for no expiry and 30 days by default. After that the token endpoint refuses it (client_secret_expired). An update made within a week of the end issues a new secret, and the old one keeps working for a day. A secret an administrator generates in Access Token Management does not expire. Remove registrations unused for deletes registered clients that were last issued a token, and last updated, more than that many days ago, a few at a time while new registrations arrive. A client you turn off in Clients can read or delete its registration, but cannot change it or turn itself back on.
Permissions, history and limits
Reading the page needs tenant.oauth.registration.read; changing the policy and statement issuers needs tenant.oauth.registration.update; creating and revoking initial access tokens needs tenant.oauth.registration.tokens. Tenant Admin holds all three. Protocol Audit records oauth.register and oauth.registration_configuration with the client, the reason for each refusal, which initial access token and statement issuer a registration used, and which metadata a narrowed registration left out. Registration accepts 60 registrations an hour per tenant. Requests without a valid initial access token also count against their network, 10 an hour each, and in Protected mode they are refused before they reach the tenant's budget, so they cannot use it up. Under Limits you can lower both and cap the number of registered clients, which also count against your client capacity. A tenant keeps up to 20 active initial access tokens and 10 statement issuers. The usage view shows each of these with its current use and reset time. A point-in-time restore keeps a narrower policy, revoked tokens, turned-off issuers and ended registration access tokens.