Client registration
1. Why register clients?
A client application must be registered with the Connect2id server before it can request tokens from it.
First and foremost this establishes the credentials to identify and / or authenticate the client in requests to the server. Second, establishes crucial security settings, such as the preferred signing algorithm for ID tokens issued to it. Without these there won’t be enough context to process the requests, as the OAuth requests are designed in general to be minimal and carry few parameters.
The registrant, which can be the developer, an administrator, or the client software itself (yes, automated self-registration is possible) needs to give several pieces of information:
-
The methods, or grant types in OAuth jargon, that the client will use to obtain the tokens. Depending on the grant type, additional parameters may be required, such as a callback URL to receive authorisation codes for the
authorization_code
grant type. -
The preferred client authentication method (e.g. shared secret or private key based) and security algorithms for the ID tokens and other objects passed between client and server, unless the client wants to stick with the default ones (
client_secret_basic
auth andRS256
for the ID token signatures). -
Metadata, such as the application’s name, logo and terms of service, to be displayed in the login / consent UI of the Connect2id server. These are not mandatory for the protocol, but meant to improve the user experience.
Note that the server’s security policy and configuration dictates what parameters will ultimately get registered. If a certain parameter is not supported or permitted, the server will try to provide a suitable default. If a parameter is found to be invalid an error will be returned.
For a successfully registered client the Connect2id server will provision:
-
A unique client ID;
-
A special registration access token to enable the client application to read, modify or delete its registration, or to refresh the client secret. Must be kept safe.
2. The client registration endpoint
Clients are registered at the registration_endpoint
advertised in the
Connect2id server metadata. Its URL has this form:
https://[base-server-url]/clients/
3. Access to the registration endpoint
Unless open registration is permitted by the server, a token is required to register a new client. This can be the configured master token for the client registration endpoint, or a specially provisioned one-time use token.
Note, even with enabled open registration, a token is required to register a
client for certain OAuth 2.0 grant types (such as password
or
client_credentials
), or to set the scope
client field.
The access token, of type bearer, must be passed with the Authorization header of the HTTP request:
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
If the token is missing and open registration is disabled, the server will respond with the following error:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
Here’s the error for an invalid token:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="invalid_token", error_description="Invalid access token"
4. Examples
Let’s now register several example clients with the demo Connect2id server, which permits open registration and has its client registration endpoint at
Endpoint URL | https://demo.c2id.com/clients/ |
4.1 Minimal registration
To register an OpenID Connect client for the default code flow it suffices to specify the redirection URL where the client expects to receive logged-in end-users with the authorisation code generated by the Connect2id server. A registration token is required unless open registration is permitted.
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
{
"redirect_uris" : [ "https://client.example.org/callback" ]
}
With curl:
curl -s -XPOST -H "Content-Type:application/json" \
-H "Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6" \
-d '{"redirect_uris":["https://client.example.org/callback"]}' \
https://demo.c2id.com/clients
To post the client metadata from a text file instead of inlined prefix @
to
the file name:
curl -s -XPOST -H "Content-Type:application/json" \
-H "Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6" \
-d @client-metadata.json \
https://demo.c2id.com/clients
Successful registration is indicated by a 201
HTTP status. The response body
will contain a JSON object with the registered and provisioned
parameters
for the client.
As explained in the introduction, the server will provision the following important parameters for the client:
-
The
client_id
andclient_secret
credentials to authenticate the client in future login and token requests. The secret, as the name implies, must be stored securely! -
The registration URI and access token to read, modify or delete the client registration later, in a RESTful manner. The token must also be stored securely. Alternatively, the registration token can be simply discarded; if some client detail needs to be modified a new registration can be made, and the client switched to the newly provisioned
client_id
.
Certain parameters will assume the following default values if not explicitly specified in the registration request:
-
The client will be registered for the OAuth 2.0
authorization_code
grant type and thecode
response type. Note, to allow the client to receive refresh tokens it must be explicitly registered for the refresh_token grant. -
The client authentication method at the token endpoint will be
client_secret_basic
. -
ID tokens issued to the client will be signed using the server’s public RSA JSON Web Key (JWK) and the
RS256
algorithm.
Other parameters matter less; you can read about them in the OpenID Connect spec and the applicable OAuth 2.0 and OpenID Connect extensions.
The response will confirm the registered callback URL. If necessary multiple
callback URLs can be registered (redirect_uris
).
HTTP/1.1 201 Created
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"client_id" : "5def774h6caci",
"client_id_issued_at" : 1412671298,
"client_secret" : "AITXP49gecnFP83u1Mjot9xz7Hgu4u4lYBrTxvNtq1k",
"client_secret_expires_at" : 0,
"registration_client_uri" : "https://demo.c2id.com/clients/5def774h6caci",
"registration_access_token" : "jZNmlyJeo3V2j14fynmDthWjbizNYe2fc5pYW27fReo",
"grant_types" : [ "authorization_code" ],
"response_types" : [ "code" ],
"redirect_uris" : [ "https://client.example.org/callback" ],
"token_endpoint_auth_method" : "client_secret_basic",
"application_type" : "web",
"subject_type" : "public",
"id_token_signed_response_alg" : "RS256",
"require_auth_time" : false
}
If the request is invalid or malformed a 400
Bad Request error is returned:
HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"error" : "invalid_redirect_uri",
"error_description" : "Invalid redirection URI(s): Redirection URIs must have a schema"
}
4.2 Allowed scope values
The scope
metadata parameter sets the scope values that the client may
request for an end-user. The syntax is the same as the
scope
authorisation request parameter, a list of space-delimited values.
The example below sets the allowed scope values to openid
, email
and
profile
. If the client makes an authorisation
request with a scope
value that isn’t
registered in the client metadata, say offline_access
, the Connect2id server
will automatically remove it from the request and it will not appear in the
consent prompt.
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"scope" : "openid email profile"
}
This behaviour is controlled by the op.authz.limitToRegisteredScope configuration property.
4.3 Allow refresh tokens
To allow a client to receive refresh tokens it must be registered for the refresh_token
grant.
Example registration allowing a client that uses the code flow to receive refresh tokens:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"grant_types" : [ "authorization_code", "refresh_token" ]
}
4.4 Client details to display to end-users
When the user’s browser is sent to the login page (technically the authorisation endpoint) of the Connect2id server, to help the end-user recognise the client application but also for legal purposes, it is helpful to display the application’s name, logo and legal links.
The client registration specs define several parameters for that:
-
client_name
– The name of the client app. This parameter should always be provided. -
logo_uri
– The logo or icon URL of the client. Must point to a suitable image to be displayed in the browser. Also good to have. -
client_uri
– Link to the home page of the client. -
policy_uri
– Link to the privacy policy document. -
tos_uri
– Link to the terms-of-service document.
To cater for international audiences the client details can be provided in multiple locales, by appending language tags to the parameter names:
"client_name#en" : "My Express Shop",
"client_name#es" : "Mi Tienda Exprés"
Let’s now register another client, and provide its name, logo and other details:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"client_name" : "My Example App",
"logo_uri" : "http://client.example.org/logo.png",
"client_uri" : "http://client.example.org",
"policy_uri" : "http://client.example.org/privacy-policy.html",
"tos_uri" : "http://client.example.org/terms-of-service.html"
}
The server response with the registration confirmation:
HTTP/1.1 201 Created
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"client_id" : "ug2sb5zkcmpsi",
"client_id_issued_at" : 1412692755,
"client_secret" : "DUdXNieQ8fwF07surrra8htYc5f_yED0MxuM21yw7W8",
"client_secret_expires_at" : 0,
"registration_client_uri" : "https://demo.c2id.com/clients/ug2sb5zkcmpsi",
"registration_access_token" : "5YHead_Ir8rNQP2KYW31XZHvca7Xk0qi6HKoS-OoTZg",
"grant_types" : [ "authorization_code" ],
"response_types" : [ "code" ],
"redirect_uris" : [ "https://client.example.org/callback" ],
"token_endpoint_auth_method" : "client_secret_basic",
"client_name" : "My Example App",
"logo_uri" : "http://client.example.org/logo.png",
"client_uri" : "http://client.example.org",
"policy_uri" : "http://client.example.org/privacy-policy.html",
"tos_uri" : "http://client.example.org/terms-of-service.html",
"application_type" : "web",
"subject_type" : "public",
"id_token_signed_response_alg" : "RS256",
"require_auth_time" : false
}
4.5 How to register a public client
OAuth defines two types of clients:
- Confidential – clients that can maintain the confidentiality of credentials that are issued to them (which is typically all server-based software).
- Public – clients that cannot be securely verified by the OAuth / OpenID Connect server as they cannot keep client credentials issued to them confidential (typically all clients that are installed on end-user devices, or web-browser based apps). Instances of such clients may share the same same client_id (such as all instances of a mobile app downloaded from an app store).
Unless specifically requested, clients will be registered as confidential and issued a client secret (alternative client credentials are available).
Before registering a public client, make sure the Connect2id server is configured to include none in the list of the supported client authentication methods.
To register a public client set the token endpoint authentication method to none. Public clients must be required to use a code challenge (PKCE, see RFC 7636), to prevent code injection (replay) and other attacks.
Example registration request for a public native client (mobile app using the code flow and a custom redirection URI):
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"application_type" : "native",
"redirect_uris" : [ "com.example.app:///auth" ],
"token_endpoint_auth_method" : "none",
"code_challenge_method" : "S256"
}
Note, the application type must be explicitly set to native to register a redirection URI with a custom scheme, or localhost as the host name.
Example registration request for a public web client (JavaScript app):
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"grant_types" : [ "authorization_code", "refresh_token" ],
"response_types" : [ "code" ],
"redirect_uris" : [ "https://myapp.example.com/?callback" ],
"token_endpoint_auth_method" : "none",
"code_challenge_method" : "S256"
}
4.6 How to register a native (mobile, desktop) client
Native applications must indicate their type in the application_type
metadata parameter, by setting it to native
, otherwise the Connect2id server
will assume a web
application.
Native applications are allowed to register the following types of redirect_uris:
-
http
URLs with alocalhost
or loopback IP –127.0.0.1
in IPv4 or0:0:0:0:0:0:0:1
(short form::1
) in IPv6. The port may be variable (see more on that below). -
https
URLs (may be claimed). -
URIs with custom URI schemes.
For testing purposes a native application may be excepted from the https
requirement for web host redirection URLs, by setting the
op.reg.rejectNonTLSRedirectionURIs
configuration property to false
.
Note that a native application also has the choice to register as a confidential client (each instance receiving a unique client_id and being required to authenticate with a client credential at the token endpoint), or as a public client (all instances sharing the same client_id, no client credential).
Public clients must be required to use a code challenge (PKCE, see RFC 7636), to prevent code injection (replay) and other attacks.
Example registration request for a public native client with a custom scheme redirect URI:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"application_type" : "native",
"redirect_uris" : [ "com.example.app:///auth" ],
"token_endpoint_auth_method" : "none",
"code_challenge_method" : "S256"
}
Example for a public native client with an HTTP localhost redirect URL:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"application_type" : "native",
"redirect_uris" : [ "http://localhost:9090/cb" ],
"token_endpoint_auth_method" : "none",
"code_challenge_method" : "S256"
}
In cases when the native application is not guaranteed to be able to bind to a
predetermined port, it should register for a variable port redirect_uri
, by
setting the port number to zero (0
):
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"application_type" : "native",
"redirect_uris" : [ "http://localhost:0/cb" ],
"token_endpoint_auth_method" : "none",
"code_challenge_method" : "S256"
}
Authorisation requests can then use any port in the 1 to 65535 range, provided the other components in the redirection URI match the registered URI exactly.
4.7 How to register for specific OAuth 2.0 grant types or response types
If the registration request doesn’t specify explicit OAuth 2.0 grant types the
assumed value is authorization_code
. As for the response types, they default
to the single code
value.
A client may 4 for other grant / response types, provided the Connect2id server is prepared to handle them. This can be checking in the advertised provider metadata, which the demo server has published at
Let’s register an OpenID Connect client for the implicit
grant. This grant provides a
simplified authorisation flow and is intended for clients implemented in a
browser with scripting language such as JavaScript. Matching response types for
the implicit grant type are id_token
and id_token token
:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"grant_types" : [ "implicit" ],
"response_types" : [ "id_token", "token id_token" ]
}
Avoid registering a client for multiple grant types, for example both
authorization_code
and implicit
, as this may lead to unwanted side
effects. If a client needs to make use of more than one
grant / flow, create separate registrations (client_id
instances) for each
one.
4.8 How to register a client for the password grant
Use of the password grant carries higher security risks. Registration for it requires the configured master token for the client registration endpoint, or a specially provisioned one-time token.
Minimal registration request for the password grant:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
{
"grant_types" : [ "password" ]
}
The scope
parameter can be used to convey to the password grant
handler the range of scope values that
the client is allowed to request:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
{
"grant_types" : [ "password" ],
"scope" : "openid email app:read app:write"
}
4.9 How to register a client for the client credentials grant
The client credentials grant is intended for clients that act on their own behalf (the client is also the resource owner), as opposed to the general OAuth case where the client acts on behalf of an end-user. This grant type is often used in microservice and B2B service scenarios.
An initial registration token is always required.
Minimal registration request:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
{
"grant_types" : [ "client_credentials" ]
}
As with the password grant client, the scope
parameter may be required by the grant
handler to bound the scope
values that the client is allowed to request:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
{
"grant_types" : [ "client_credentials" ],
"scope" : "myapi:post myapi:get myapi:delete"
}
JWT and mutual TLS based authentication at the token
endpoint is recommended for best security.
Example registration for a client which is going to authenticate with a JWT
signed with an EC private key using the EC256
algorithm, the client’s public
key(s) for validating the JWT signature are published at an URL:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
{
"grant_types" : [ "client_credentials" ],
"token_endpoint_auth_method" : "private_key_jwt",
"token_endpoint_auth_signing_alg" : "EC256",
"jwks_uri" : "https://client.example.com/jwks.json",
"scope" : "myapi:post myapi:get myapi:delete"
}
4.10 How to register a client for the token exchange grant
The token exchange grant lets clients obtain an access or ID token (with optional refresh token) in exchange for some valid and recognised token, which can be local or come from a third party domain. The exchange properties and logic are controlled by means of a configurable plugin.
An initial registration token is always required.
Minimal registration request enabling the client to submit tokens for exchange:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
{
"grant_types" : [ "urn:ietf:params:oauth:grant-type:token-exchange" ]
}
When the client is issued with a refresh token for a successful exchange it must also be registered for the refresh token grant. Otherwise the client won’t be able to use the refresh token.
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
{
"grant_types" : [ "urn:ietf:params:oauth:grant-type:token-exchange",
"refresh_token" ]
}
4.11 How to register a grant-less client
The Connect2id server supports registration of special “grant-less” clients that will not be using the standard token endpoint, for instance clients to be issued tokens via the direct authorisation endpoint.
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
{
"grant_types" : [ ],
"response_types" : [ ]
}
4.12 How to require use of PKCE
The Proof Key for Code Exchange by OAuth Public Clients (PKCE) is a security extension originally devised to prevent code injection attacks on clients that cannot authenticate at the token endpoint, and which was later found to be useful against other attack vectors and thus became mandatory in OAuth 2.1.
To require a client to use the recommended S256
code challenge method:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"code_challenge_method" : "S256"
}
The code_challenge_method
metadata field became available
v13.0.
4.13 How to register a client for JWT authentication
JSON Web Token (JWT) assertions, specified in RFC 7523 as well as in section 9 of OpenID Connect, is a secure method for authenticating clients at the token endpoint. Instead of sending a password (the client secret) along with each request, which is how basic authentication works, the client generates a cryptographic proof of key possession.
The proof is encoded as a JWT which carries following claims:
- iss The JWT issuer, which is represented by the client_id.
- sub The JWT subject, which is again set to the client_id.
- aud The JWT audience, set to the token endpoint URL.
- exp The JWT expiration.
- iat The JWT issue time (optional).
- jti A unique identifier for the JWT.
Example JWT claims:
{
"iss" : "oe7aiz60",
"sub" : "oe7aiz60",
"aud" : "https://demo.c2id.com/token",
"exp" : 1453021544,
"jti" : "Eefaevo0"
}
There are two types of JWT authentication, depending on the key used to secure the assertion:
-
client_secret_jwt – The JWT is secured with a Hash-based Message Authentication Code (HMAC) computed with the client_secret.
-
private_key_jwt – The JWT is signed with an asymmetric key (RSA or EC) that belongs to the client.
The server authenticates the client by verifying the HMAC with the registered client_secret (for client_secret_jwt) or by checking the RSA / EC signature with the client’s registered public key (for private_key_jwt). The JWT issuer, subject, intended audience and expiration are also checked.
What are the security advantages over basic authentication?
- Prevents exposure and replay of the client credential if the client is subjected to a malicious endpoint attack. A JWT created for a malicious token endpoint cannot be replayed with the legitimate authorisation server because of the audience (aud) check.
- Also prevents exposure of the client credential if for some reason the token request is accidentally sent out via plain HTTP (instead of HTTPS).
- If the client uses multiple authorisation servers, private_key minimises the number of credentials that need to be stored.
The Connect2id server supports JWT authentication out of the box. However, if you’ve upgraded from an old server version, make sure JWT auth is indeed configured and so are the JWS crypto algorithms for it.
To register a client for client_secret_jwt authentication with JWS HS256
make a request like this:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"token_endpoint_auth_method" : "client_secret_jwt",
"token_endpoint_auth_signing_alg" : "HS256"
}
To register a client for private_key_jwt authentication generate an RSA or EC key pair, and store the private key securely. Export the public key to a JSON Web Key (JWK) set, so that it can be registered with the Connect2id server. To ease key rollover, the JWK should be given a unique key ID (kid) within the set. You can use the Connect2id JWT library to generate and export RSA / EC keys to the JWK format.
Example registration request for private_key_jwt authentication with JWS
RS256
:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"token_endpoint_auth_method" : "private_key_jwt",
"token_endpoint_auth_signing_alg" : "RS256",
"jwks" : { "keys" : [ { "e" : "AQAB", "n" : "gmlDX_mgMcHX.." ] }
}
If the Connect2id server has a client certificate verifier for
private_key_jwt, to
enable clients to pass their public key in a qualified certificate put in the
JWT’s x5c
header parameter, there is no need to register a client JWK set.
The registration request is similar, save that there is no jwks
or jwks_uri
client metadata field now:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"token_endpoint_auth_method" : "private_key_jwt",
"token_endpoint_auth_signing_alg" : "RS256" }
}
4.14 How to register a client for mutual TLS authentication and client X.509 certificate bound tokens
The Mutual TLS Profile for OAuth 2.0 enables clients to authenticate with a X.509 certificate and receive access tokens bound to it, enhancing their security over the regular Bearer type.
There are two variants of client certificate authentication:
-
tls_client_auth – The client certificate is issued by a trusted Certificate Authority (CA).
-
self_signed_tls_client_auth – The client certificate is self-signed.
To register a client for tls_client_auth set the
tls_client_auth_subject_dn
metadata parameter to the expected certificate
subject distinguished name (DN). Also, make sure
tls_client_certificate_bound_access_tokens
is set.
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"token_endpoint_auth_method" : "tls_client_auth",
"tls_client_auth_subject_dn" : "cn=appX",
"tls_client_certificate_bound_access_tokens" : true
}
To register a client for self_signed_tls_client_auth its certificate must
be supplied in the client’s
registration.
This is done by putting it inside the
x5c (X.509 certificate
chain) parameter of a public JWK. Since the certificate is self-signed the
x5c
array length is exactly one. The JWK type and public key parameters must
match those of the included certificate. The JWK itself is supplied within a
standard JWK set structure:
- by value using the
jwks
parameter, or - by URL using the
jwks_uri
parameter.
Example JWK set with a single RSA key that includes a self-signed RSA certificate:
{
"keys": [
{
"kty" : "RSA",
"alg" : "RS256",
"use" : "sig",
"kid" : "1",
"n" : "9HrVGuF7iyoR9oOIu-kISItytKxDLb-BdGmsqx-EBhVI11Q4DhfoxzNyaOWPaPcR6RpPbVAFY-drZgEH4SAQcVUzCUB2DKjLaZaBbCOWu3NYnif2XN0EwMiw4X7XD1qsvzoZbM72ApJ9AcZgPpq9suv8fZoOc__-lhTLTqAK5Ww9j-a_Fh3ADzWYcUfaHXZqQSMfIZTx2b0_X5Uech4ILrFUiEPhpf9zEmF5_Git2UYScwfXb9mW2OjXVVrE8zuI_RH97mSV82QVD_pr2Ikd1LJgB1xYkms5kUlzAm2diw60nqty3KMp_XAUe8fv0vD58Oqe2rNvl-4y8KIBWi8piQ",
"e" : "AQAB",
"x5c": [ "MIICljCCAX6gAwIBAgIGAYgE5hzPMA0GCSqGSIb3DQEBCwUAMAwxCjAIBgNVBAMMATEwHhcNMjMwNTEwMDkwMjQ5WhcNMjQwMzA1MDkwMjQ5WjAMMQowCAYDVQQDDAExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9HrVGuF7iyoR9oOIu+kISItytKxDLb+BdGmsqx+EBhVI11Q4DhfoxzNyaOWPaPcR6RpPbVAFY+drZgEH4SAQcVUzCUB2DKjLaZaBbCOWu3NYnif2XN0EwMiw4X7XD1qsvzoZbM72ApJ9AcZgPpq9suv8fZoOc//+lhTLTqAK5Ww9j+a/Fh3ADzWYcUfaHXZqQSMfIZTx2b0/X5Uech4ILrFUiEPhpf9zEmF5/Git2UYScwfXb9mW2OjXVVrE8zuI/RH97mSV82QVD/pr2Ikd1LJgB1xYkms5kUlzAm2diw60nqty3KMp/XAUe8fv0vD58Oqe2rNvl+4y8KIBWi8piQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQC9YQvdqFUfXXOEw0X+z/14RQwAVzTK1cqqtBZJTmUCyXc51jm5hfsN3jnoYEmS888EM55KWF1PlPr0G1P7kvs6sMhhKRJQigxeQmw1YHOIWLRHywI+M0ZLpDcBRLbWtEBPIEuN4DLXM9vnGX/UF05Zgk5/U1oM8Vg1MIfXaIIwshpB3y41vRSJXrdrqxGIwApdCRZX6usYZpiHmbkLWN+0t/jsEggmCoPfOfZKwFTetkAU+hxGE4QJPQ+I/ahhu1XCrejMEAShV2pLFm9VP4ECwjlbQjAqmInE7GhZlerNdwYEbLjr5yOnVLT+XJUPjDdzs/ImDk/8mEQ0qpzSZxTl" ]
}
]
}
The JWK and self-signed client certificate can be generated programmatically.
An example complete registration request:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"token_endpoint_auth_method" : "self_signed_tls_client_auth",
"jwks" : {
"keys": [
{
"kty" : "RSA",
"alg" : "RS256",
"use" : "sig",
"kid" : "1",
"n" : "9HrVGuF7iyoR9oOIu-kISItytKxDLb-BdGmsqx-EBhVI11Q4DhfoxzNyaOWPaPcR6RpPbVAFY-drZgEH4SAQcVUzCUB2DKjLaZaBbCOWu3NYnif2XN0EwMiw4X7XD1qsvzoZbM72ApJ9AcZgPpq9suv8fZoOc__-lhTLTqAK5Ww9j-a_Fh3ADzWYcUfaHXZqQSMfIZTx2b0_X5Uech4ILrFUiEPhpf9zEmF5_Git2UYScwfXb9mW2OjXVVrE8zuI_RH97mSV82QVD_pr2Ikd1LJgB1xYkms5kUlzAm2diw60nqty3KMp_XAUe8fv0vD58Oqe2rNvl-4y8KIBWi8piQ",
"e" : "AQAB",
"x5c": [ "MIICljCCAX6gAwIBAgIGAYgE5hzPMA0GCSqGSIb3DQEBCwUAMAwxCjAIBgNVBAMMATEwHhcNMjMwNTEwMDkwMjQ5WhcNMjQwMzA1MDkwMjQ5WjAMMQowCAYDVQQDDAExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9HrVGuF7iyoR9oOIu+kISItytKxDLb+BdGmsqx+EBhVI11Q4DhfoxzNyaOWPaPcR6RpPbVAFY+drZgEH4SAQcVUzCUB2DKjLaZaBbCOWu3NYnif2XN0EwMiw4X7XD1qsvzoZbM72ApJ9AcZgPpq9suv8fZoOc//+lhTLTqAK5Ww9j+a/Fh3ADzWYcUfaHXZqQSMfIZTx2b0/X5Uech4ILrFUiEPhpf9zEmF5/Git2UYScwfXb9mW2OjXVVrE8zuI/RH97mSV82QVD/pr2Ikd1LJgB1xYkms5kUlzAm2diw60nqty3KMp/XAUe8fv0vD58Oqe2rNvl+4y8KIBWi8piQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQC9YQvdqFUfXXOEw0X+z/14RQwAVzTK1cqqtBZJTmUCyXc51jm5hfsN3jnoYEmS888EM55KWF1PlPr0G1P7kvs6sMhhKRJQigxeQmw1YHOIWLRHywI+M0ZLpDcBRLbWtEBPIEuN4DLXM9vnGX/UF05Zgk5/U1oM8Vg1MIfXaIIwshpB3y41vRSJXrdrqxGIwApdCRZX6usYZpiHmbkLWN+0t/jsEggmCoPfOfZKwFTetkAU+hxGE4QJPQ+I/ahhu1XCrejMEAShV2pLFm9VP4ECwjlbQjAqmInE7GhZlerNdwYEbLjr5yOnVLT+XJUPjDdzs/ImDk/8mEQ0qpzSZxTl" ]
}
]
},
"tls_client_certificate_bound_access_tokens" : true
}
4.15 How to require Pushed Authorisation Requests (PAR) for a client
A client can be required to use the PAR endpoint by setting the
require_pushed_authorization_requests
parameter:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"require_pushed_authorization_requests": true
}
This will force upfront authentication of the client (for a confidential client), before involving the end-user with any login and consent related interactions.
4.16 How to register a client for JWT-secured authorisation requests (JAR)
JWT-secured authorisation requests (JAR) (RFC 9101), also called request objects in OpenID Connect, enable signing and optional encryption of the parameters.
Clients that make signed authorisation requests must provide their JWK set, by
value (jwks
) or by reference (jwks_uri
), so that the Connect2id server can
validate JWT signatures.
To register a client using public RSA keys for RS256 signed authorisation requests and thus also prevent it from making plain requests:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"token_endpoint_auth_method" : "private_key_jwt",
"token_endpoint_auth_signing_alg" : "RS256",
"jwks_uri" : "https://client.example.com/jwks.json",
"request_object_signing_alg" : "RS256"
}
If the client is going to be passing the request JWTs by one or more URLs they
must be pre-registered in request_uris
:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"token_endpoint_auth_method" : "private_key_jwt",
"token_endpoint_auth_signing_alg" : "RS256",
"jwks_uri" : "https://client.example.com/jwks.json",
"request_object_signing_alg" : "RS256",
"request_uris" : [ "https://client.example.com/requests/a1.jwt",
"https://client.example.com/requests/a2.jwt",
"https://client.example.com/requests/a3.jwt" ]
}
The request JWTs can be additionally set for confidentiality, for example by
encrypting them with RSA-OAEP-256
and A128CBC-HS256
to the encryption RSA
key published by the Connect2id server:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"token_endpoint_auth_method" : "private_key_jwt",
"token_endpoint_auth_signing_alg" : "RS256",
"jwks_uri" : "https://client.example.com/jwks.json",
"request_object_signing_alg" : "RS256",
"request_object_encryption_alg" : "RSA-OAEP-256",
"request_object_encryption_enc" : "A128CBC-HS256"
}
4.17 How to register a client for JWT-secured authorisation responses (JARM)
When a client sets the response_mode authorisation
request parameter to jwt
the response parameters will be delivered to the
callback redirect_uri
in a RS256 signed JWT
(JARM).
To cause the JWT to be signed with a different JWS algorithm than the default
RS256
, or, to return all authorisation responses as a JWT, regardless of how
the response_mode
is set, register the client explicitly for a signing JARM
algorithm.
Example registration for a client expecting authorisation responses to be
secured with HMAC using the HS256
algorithm:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json`
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"authorization_signed_response_alg" : "HS256"
}
The JWT responses can be additionally encrypted with JWE, using public key
encryption or a shared key derived from the client_secret
.
If the client is set up to receive JWT responses encrypted to a public key in the client JWK set, the JWK set must be provided in the registration, either by value or by URL.
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"jwks_uri" : "https://client.example.com/jwks.json",
"authorization_signed_response_alg" : "RS256",
"authorization_encrypted_response_alg" : "RSA-OAEP-256",
"authorization_encrypted_response_enc" : "A128CBC-HS256"
}
4.18 How to register a client to receive encrypted ID tokens or UserInfo
Example client registration request stating that ID tokens are to be first signed with RSA PKCS #1 and then encrypted with a 128-bit AES key derived from the client secret, using the AES GCM KW algorithm:
POST /clients HTTP/1.1
Host: demo.c2id.com
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
Content-Type: application/json
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"id_token_signed_response_alg" : "RS256",
"id_token_encrypted_response_alg" : "A128GCMKW",
"id_token_encrypted_response_enc" : "A128CBC-HS256"
}
Registering a client to receive signed and encrypted UserInfo JWTs is similar:
POST /clients HTTP/1.1
Host: demo.c2id.com
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
Content-Type: application/json
{
"redirect_uris" : [ "https://client.example.org/callback" ],
"userinfo_signed_response_alg" : "RS256",
"userinfo_encrypted_response_alg" : "A128GCMKW",
"userinfo_encrypted_response_enc" : "A128CBC-HS256"
}
4.19 How to include additional client data
In case you need to store additional details about a client that don’t fit into the standard parameter set the custom data parameter comes to help:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
{
"redirect_uris" : [ "https://myapp.example.com/callback" ],
"data" : { "reg_type" : "3rd-party",
"approved" : true,
"author_id" : 792440 }
}
The data parameter permits arbitrary content packaged in a JSON object. To
set it you will need the master registration token or a one-time
access token with a client-reg:data
scope.
4.20 How to register a client with a preset client_id or client_secret
When the Connect2id server registers a new client it generates a
random client_id
for it.
If the chosen client authentication method, ID token JWS algorithm or UserInfo
JWS algorithm require it, it also generates a secret of the appropriate length.
This is the standard behaviour and fine for most situations. You may however want to preset the client identifier and / or secret to a specific value, if migrating existing clients to the Connect2id server for example.
To do that make a registration request with the master API access token using the following non-standard parameters to specify the desired values:
-
preferred_client_id
to preset the client identifier -
preferred_client_secret
to preset the client secret (also works when updating an existing client registration).
For example, to register a client with a preset client_id
and client_secret
for the password grant:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
{
"grant_types" : [ "password" ],
"preferred_client_id" : "123456",
"preferred_client_secret" : "ahL7AhthchiNg6beAo5HeijeThae3deiChab7ajiVuip2eodesoBie0ufohtiiK4"
}
The server will then register the client under the preferred identifier and secret, provided there’s no collision with an existing client and the secret is not too short.
In case the client_id
is already taken you will get a standard
invalid_client_metadata
error:
HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"error" : "invalid_client_metadata",
"error_description" : "Invalid client metadata field: The preferred client_id is already in use"
}
In case the secret is too short for the chosen client authentication method, ID token JWS algorithm or UserInfo JWS algorithm, the Connect2id server will return the following error:
HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"error" : "invalid_client_metadata",
"error_description" : "Invalid client metadata field: The preferred secret must be at least 256 bits"
}
The preset client secret facility can also be used to import hashed or otherwise encoded client secrets from another server:
POST /clients HTTP/1.1
Host: demo.c2id.com
Content-Type: application/json
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
{
"grant_types" : [ "password" ],
"preferred_client_id" : "123456",
"preferred_client_secret" : "$2a$04$a9uQ9Ka0usxqTCp/1je2iuS.qnVsXKe0Gjhh5kPEhnbInkseODhgS"
}
5. References
Client registration is defined in three specs:
-
OAuth 2.0 dynamic client registration – the core protocol and the common parameters for registration of OAuth 2.0 clients.
-
OAuth 2.0 dynamic client management – extends the core protocol with additional requests for viewing, updating and deleting client registrations.
-
OpenID Connect dynamic client registration – extends the core protocol with additional registration parameters required by OpenID Connect.
6. Frequently asked questions (FAQ)
6.1 Why is the client authentication method locked down at registration time?
The token_endpoint_auth_method
is locked down at registration time
intentionally, to prevent accidental or intentional downgrades. Mostly to
prevent a client registered for JWT authentication to use the less
safe basic method.
6.2 Can I register a client for multiple grants / response types?
You may, however this complicates the management of the client account, and may
also lead to unwanted side effects. For example, a client registered for the
code
as well as the implicit
grants may not be issued a refresh token,
or may have its refresh token invalidated.
We recommend that you always register a client for a single grant / flow only.
If a client needs to make use of more than one grant / flow, register a
separate client identity (client_id
) for each one.