Dynamic Client Registration Authentication Methods
On this page
Getting started with DCR
The Dynamic Client Registration (DCR) Overview article provides an overview of the RFC7591 standard and provides a summary of the two OAuth clients involved in a DCR flow:
Client | Usage |
---|---|
DCR Initial Client | An initial client used to send a Registration Request, to create an application client |
Application Client | Created by the dynamic client registration request, to return a generated client_id , along with a client_secret in some cases |
For a getting started guide on DCR, see the Using Dynamic Client Registration article, which provides example registration request and response messages.
Main DCR Use Cases
Dynamic client registration needs to be secured in order to prevent a malicious party gaining access, and how this is done will depend upon your use case. This article will therefore describe the DCR building blocks and some common approaches.
Mobile High Security
One of the main use cases for DCR is to strengthen mobile security, so that each installed instance of the mobile app has a unique client_id
and client_secret
that is then used to protect requests for OAuth tokens, as described in Mobile Best Practices. In some setups this fits neatly with Mobile Device Management (MDM) systems used to prepare devices given to company employees. MDM systems can provision each device with a user specific secret, such as a client certificate and key, that is then also used for DCR authentication.
APIs with Dynamic Clients
The second main use case for DCR is when a company wants to provide API access for business partners in a dynamic manner. The Open Banking initiative is a great example of this use case, which encourages business innovation. Banks must expose APIs according to regulations, enabling an ecosystem where Third Party Providers (TPP)
, such as online retailers, can securely onboard with no delays, to enable their users to make online purchases via their bank accounts.
Portals and Management Systems
Another common DCR use case is when creating online accounts with a technology provider. A credential is often provided after registering, then used to create OAuth clients for applications. This type of solution sometimes only provides fairly basic security, targeted at developers.
Securing DCR
The main authentication techniques are summarized below, providing a toolbox for managing dynamic client registration and adapting it to your needs. These tools can be applied in multiple ways, and we will drill into common solutions in this article.
Authentication Technique | Behavior Summary |
---|---|
User Authenticates | An end user supplies credentials in order to get an initial access token used to perform the DCR registration |
Client Authenticates | A client application supplies credentials in order to get an initial access token used to perform the DCR registration |
Mutual TLS | The DCR registration is performed over a Mutual TLS channel, to securely identify a trusted client |
Software Statement | The client includes a JWT in the registration request with further information that is verified before registration is allowed |
Custom Pre-Processing | The Identity Server enables custom logic to be applied during a DCR registration request |
User Authentication Methods
DCR user authentication is used primarily in mobile use cases, when you want to strengthen mobile OAuth security but cannot control the devices via MDM, e.g. for an app deployed to internet users. In this case the user's credentials can be used for both DCR authentication and also the app's main OAuth flow. The app can then use mobile secure storage to save the secret, then use it later, in requests for tokens. This results in the following overall flow:
In the Curity Identity Server, the user authenticates behavior is configured by enabling the Authenticate User By
option, then configuring the initial DCR client:
Code Flow
It is possible to use various UI flows to sign the user in, such as the Implicit Flow, though these days you would most commonly use Authorization Code Flow with PKCE instead, and an example implementation is provided in the Mobile DCR tutorial. The app first performs an OpenID Connect redirect with the dcr
scope, then the user enters their credentials:
GET /oauth/v2/oauth-authorize HTTP/1.1Host: login.example.comclient_id=mobile-dcr-initial-client&redirect_uri=https://mobile.example.com&response_type=code&code_challenge=l9QIPE4TFgW2y7STZDSWQ4Y4CQpO8W6VtELopzYHdNg&code_challenge_method=S256&state=NlAoISfdL1DxPdNGFBljlVuB1GDjgGARmqDcxtHhV8iKNYu6ECS2KOavDHpI3eLN&scope=dcr
The returned authorization code is then swapped for a DCR access token using a standard authorization code grant message:
POST /oauth/v2/oauth-token HTTP/1.1Host: login.example.comContent-Type: application/x-www-form-urlencodedgrant_type=authorization_code&client_id=mobile-dcr-initial-client&redirect_uri=https://mobile.example.com&code=YFFX2HmFNnrMS8alWIZH83oim9ZHgwRh&code_verifier=ItJtBXUGtHs-3FpUHB8qW9uJ00XcwTfeiZdLGquawMg
The mobile app then sends the DCR access token in a registration request to the Identity Server's DCR endpoint. The details sent indicate the flow the created client will use later, and in this example the code flow is specified, since that is the standard option for mobile apps:
POST /token-service/oauth-registration HTTP/1.1Host: login.example.comAuthorization: Bearer e99ab41e-52a1-4fa3-b21b-fb95a398c33aContent-Type: application/json{"redirect_uris":["io.curity.dcrclient:/callback"],"post_logout_redirect_uris":["io.curity.dcrclient:/logoutcallback"],"application_type":"native","grant_types":["authorization_code"],"scope":"openid profile"}
The response to the client will then include the dynamically added client_id
and client_secret
, which the app will then use from that point forwards:
{"client_id": "87f1d9de-de2f-4e96-b27b-882cce0a3352","client_secret": "tfs9nad3dweFAa1CqpUj5p6NC4-092hb5Gg4SVRhOkc",}
After this one-time registration, the user will be redirected again, to perform the newly created client's OAuth flow, and this will be a Single Sign On event, since the initial login will have resulted in the Identity Server issuing a session cookie. On all subsequent logins from this point forwards, there is only a single user redirect.
Delivery of a DCR Access Token
Alternative options can be used to deliver the initial access token with the dcr
scope to the user's device, via an out-of-band mechanism. A common option is for a back end service to perform client authentication to get the DCR access token, then deliver that to the mobile device, e.g. via a mobile push notification.
Client Authentication Methods
When client authentication is configured, an initial client is created which must be used in order to get a DCR access token, via the Client Credentials flow. The general flow is illustrated below, and multiple forms of client credential can be used, which will be summarized in the following sections.
In the Curity Identity Server this behavior is configured by enabling the Authenticate Client By
option, then configuring the initial DCR client:
Trust
Before a client authenticates, there needs to be some form of trust configured, to prevent a malicious party from gaining access. The following two main options are used to manage trusted clients:
Trust Mechanism | Usage |
---|---|
Central Authority | Clients have to be approved by an industry specific authority and are then issued with a digital client credential, which the service provider can trust, without the need for any manual steps. |
Out of Band | The service provider uses an out of band mechanism to approve future clients as a prerequisite. This might involve a people process to configure trusted digital credentials, to enable dynamic registration at a later time. |
Trust between companies most commonly is based on Public Key Infrastructure (PKI), in which case either client certificates or asymmetric keys are used to secure the DCR process.
Discovering Authentication Methods
To dynamically register, a client can start by downloading the Provider Metadata from the OpenID Connect Discovery Endpoint. The client authentication methods that are active are returned in the following response fields:
Metadata Field | Usage |
---|---|
token_endpoint_auth_methods_supported | Indicates the forms of client authentication that can be used, which may include Mutual TLS and JWT client assertions |
token_endpoint_auth_signing_alg_values_supported | Indicates token signing algorithms that will be accepted when a JWT client assertion is supplied as a client secret |
The possible authentication methods are briefly summarized below, and the most secure options are private_key_jwt
and tls_client_auth
. Using symmetrically signed JWTs is not usually a secure option for DCR so it will not be discussed further in this article.
Token Endpoint Authentication Method | Behavior |
---|---|
client_secret_basic | A string client secret sent in the HTTP Authorization Header as a basic credential |
client_secret_post | A string client secret sent as a form post |
client_secret_jwt | A JWT that is symmetrically signed and uses a signing key known by both the client and the Identity Server |
private_key_jwt | A JWT that is asymmetrically signed, with the private key only known by the client |
extended options | Custom values can also be returned, and the Curity Identity Server adds tls_client_auth when Mutual TLS is enabled |
String Client Secret
In some setups it is possible to use a simple string client_secret to get the initial DCR access token. This is the most basic form of the client credentials flow and does not provide strongest security. The client credential is sent via either client_secret_basic
or client_secret_post
and this example request uses the POST option:
POST /oauth/v2/oauth-token HTTP/1.1Host: login.example.local:8443Content-Type: application/x-www-form-urlencodedgrant_type=client_credentials&client_id=dcr-initial-client&client_secret=my-secret&scope=dcr
In the Curity Identity Server this would require the initial DCR client to be configured with the same client_id
and client_secret
as the caller, so that the server can validate credentials when DCR requests are received:
This type of option might be used in an portal system, where the user is given the credential after registering. It might also be used in scenarios where the client credentials can be exchanged securely in advance, via an out-of-band mechanism.
Client Certificate Secret
A higher security option is to send a client credential that proves proof of ownership of a client certificate and key. This might be used in a B2B API use case, or with MDM when there is a client certificate installed on the device. A Mutual TLS channel is then used to get the DCR access token, as in this example curl request:
curl -X POST "https://login.example.com/oauth/v2/oauth-token-mutual-tls" \--cert "example.clientcert.p12":"mycert-privatekeypassword" \--cert-type P12 \-H "Content-Type: application/x-www-form-urlencoded" \-d "grant_type=client_credentials" \-d "client_id=dcr-initial-client" \-d "scope=dcr"
In this setup the DCR initial client is commonly configured to only allow client certificates from an approved issuer, such as a business partner or MDM system. Various PKI options can be used to verify the client certificate, and the configuration should allow the client certificate to be renewed without breaking changes.
The infrastructure involved in managing Mutual TLS and transport level security can be tricky to manage if you are not familiar with it, and typically requires dedicated ports or endpoints. For an end-to-end worked example, see the Mutual TLS API tutorial.
JWT Client Assertions
A high security option that may be easier to manage is to use PKI via message level security and asymmetric keys. This involves installing a JSON Web Key in the client, then writing code to create and send a JWT Assertion as the client credential. An example request to authenticate and get a DCR access token is shown here, and note that the client_id
field is sent as a claim in the JWT assertion:
POST /oauth/v2/oauth-token HTTP/1.1Host: login.example.local:8443Content-Type: application/x-www-form-urlencodedgrant_type=client_credentials&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=eyJraWQiOiIxNjE5Nzc1NDQ...&scope=dcr
The DCR initial client would then be configured to only accept trusted JWT assertions. Although this can be done by specifying the asymmetric public key value, it is more usual to configure the trusted JWKS URI of the client, since this enables keys to be rotated.
Registration
Once a client has completed DCR authentication and has a valid DCR access token, the registration request will be sent. The fields sent are explained in the Client Metadata section of the DCR specification. A key behavior of the DCR request is to express how the application client created will authenticate later. This is managed by sending the following values:
Registration Field | Usage |
---|---|
grant_types | This will be authorization_code when registering a mobile client, or client_credentials when registering an API client |
token_endpoint_auth_method | One of the token_endpoint_auth_methods_supported values discussed earlier |
jwks_uri | A URL that will later be used to get token signing public keys for validating client assertions, for clients that use the private_key_jwt method |
jwks | A token signing public key passed by value and used later to validate client assertions, for clients that use the private_key_jwt method |
For clients that authenticate via JWT assertions, it is most standard to supply the jwks_uri
field. The jwks
field is for clients that cannot provide a URL, and might be used by a standalone mobile app, but this has the disadvantage that the key cannot easily be rotated, so this is rarely used in practice.
Financial-grade DCR Authentication
This section summarizes some advanced DCR patterns used in Open Banking, where a trusted authority provides client credentials along with additional details about the client identity, and the server must implement some extended validation during DCR requests.
Mutual TLS
Instead of using an initial client and a DCR access token, it is possible to authenticate during the main DCR registration request, using a Mutual TLS tunnel and a trusted client certificate. In this case there is no need for an initial access token with the dcr
scope, or a DCR initial client. This option is commonly used in financial-grade scenarios, where the application client will then also use Mutual TLS and Certificate Bound Access Tokens to call APIs.
The end-to-end flow might then look like this, where the client uses a Mutual TLS tunnel for all requests. It is possible to use a Mutual TLS tunnel all the way through to back end components, or Mutual TLS can be terminated and verified at the reverse proxy, which is commonly done for API requests:
In the Curity Identity Server this results in the following configuration, where one or more trusted issuers are specified. In Open Banking, only client certificates issued by the trusted central authority are allowed, e.g. by eIDAS in Europe. Therefore the authority's root and intermediate certificates would be configured as trusted issuers, meaning that client certificates from any other issuer would be rejected:
Software Statements
When a central authority approves a client for Open Banking, a credential is issued, most commonly in the form of a client certificate and key. In addition the authority can also provide claims, such as business roles assigned to the client, so that the service provider receives useful context.
The client downloads this information from the authority at runtime, as a JWT signed assertion, then sends it in the registration request in the software_statement field. The registration request will then include both the assertion and details on how the final client will authenticate later:
{"token_endpoint_auth_method": "tls_client_auth","tls_client_auth_subject_dn": "CN=tpp.example.com,OU=368a900d-89a3-4c59-a624-1387f1b541fb,O=Testing Bank,L=Sao Paulo,ST=SP,C=BR","software_statement": "eyJraWQiOiItMTY1ODk3MjgyNSIsIng1dCI6 ..."}
Validating the software statement is domain specific work that must be done in custom code, similar to how an API validates claims. This requires a setup where DCR pre-processing can be run before forwarding the registration request to the Identity Server.
DCR Pre-Processing
In some industry sectors, authorities publish regulations on how incoming DCR requests must be validated, and the logic may differ depending on the country or region. This will require standards based security verification from the Identity Server, and also enforcement of business rules associated with the software statement.
Typically the service provider will need to implement a solution using the extensibility features of the Identity Server or by coding it in a reverse proxy, before the request is routed to the Identity Server. The following resources provide further details on an advanced use case:
- Open Banking Brazil Use Case
- End-to-end DCR Request Validation via the Curity Identity Server
- End-to-end DCR Request Validation via a Reverse Proxy
Although these links are focused on a particular industry sector and region, the techniques used are general security design patterns for enabling dynamic business, and could be applied to other use cases. The ability to receive custom data via claims, then verify them both digitally and in business terms, enables secure immediate onboarding.
Dynamic Client Management
This article has focused primarily on the DCR behavior from the RFC7591 standard, and the result will be that details for each unique client are stored in a database table, which in the Curity Identity Server is named dynamically_registered_clients
. Each database row will contain the information from the DCR response message, and for a mobile client this may include data similar to this:
{"default_acr_values": ["urn:se:curity:authentication:html-form:Username-Password"],"application_type": "native","registration_client_uri": "https://baa467f55bc7.eu.ngrok.io/token-service/oauth-registration/87f1d9de-de2f-4e96-b27b-882cce0a3352","registration_access_token_expires_in": 31536000,"registration_access_token": "e99ab41e-52a1-4fa3-b21b-fb95a398c33a","client_id": "87f1d9de-de2f-4e96-b27b-882cce0a3352","token_endpoint_auth_method": "client_secret_basic","scope": "openid profile","client_id_issued_at": 1624011134,"client_secret": "tfs9nad3dweFAa1CqpUj5p6NC4-092hb5Gg4SVRhOkc","id_token_signed_response_alg": "RS256","grant_types": ["authorization_code", "refresh_token"],"subject_type": "public","redirect_uris": ["io.curity.dcrclient:/callback"],"post_logout_redirect_uris":["io.curity.dcrclient:/logoutcallback"],"client_secret_expires_at": 0,"token_endpoint_auth_methods": ["client_secret_basic", "client_secret_post"],"response_types": ["code", "id_token"],"refresh_token_ttl": 3600}
The client's DCR data may then need to be updated in future, which is managed by including a Registration Access Token
in the response, which the client app must save. To make updates the client uses Dynamic Client Registration Management, as defined in RFC7592, and sends this token.
Template Clients
For mobile clients, using a separate dynamic client per device can result in a lot of duplicated settings, so an extended option called Templatized DCR is also provided in the Curity Identity Server. This enables values such as redirect_uri
and scope
to be managed centrally, so that any configuration changes immediately come into effect for all dynamic clients that used the template to register.
When using template clients, one of the Client Authenticates
or User Authenticates
options must be used, and the client must always use a DCR access token to register. The initial client authentication can continue to be done using client certificates or client assertions. During registration the template client is referenced via the software_id field, which is used to group related DCR clients:
POST /token-service/oauth-registration HTTP/1.1Host: login.example.comAuthorization: Bearer e99ab41e-52a1-4fa3-b21b-fb95a398c33aContent-Type: application/json{"software_id": "dcr-template-client"}
The registration response is then the same as previously, and each mobile instance receives a different client_id
and client_secret
. The app will save the secret to the device's built-in secure storage, then use it to strengthen token requests to the Identity Server.
{"client_id": "87f1d9de-de2f-4e96-b27b-882cce0a3352","client_secret": "tfs9nad3dweFAa1CqpUj5p6NC4-092hb5Gg4SVRhOkc",}
Conclusion
The two main use cases for Dynamic Client Registration are hardening mobile security and immediate access to external APIs. There are multiple ways to manage DCR securely, and the options chosen will depend on your scenarios, though the most secure solutions are based on public key cryptography.
Authentication is done by either getting an initial DCR access token with a dcr
scope, or using Mutual TLS for the main DCR registration request. The capabilities described in this article are part of your security toolbox and should be provided by your Identity and Access Management (IAM) system.
Gary Archer
Product Marketing Engineer at Curity
Join our Newsletter
Get the latest on identity management, API Security and authentication straight to your inbox.
Start Free Trial
Try the Curity Identity Server for Free. Get up and running in 10 minutes.
Start Free Trial