An OAuth client can be configured statically through the Web UI, the Command Line Interface or through the
RESTCONF API. The client is identified by a client_id, the value that is used throughout performing the
different OAuth (RFC 6749) and OpenId Connect (OpenId Connect Core Specification) flows.
To store clients in a Data Source instead of in configuration, see Database Client Management.
When choosing a value for client_id, the whitespace character is prohibited. Other than that, all printable
ASCII-characters are allowed. The client_id value has no technical limitations on its length. While the Web UI
treats special characters differently, it is always possible to set a client_id-value through the CLI or through
Client capabilities define the capabilities that should be allowed for a given client. The capabilities can be broadly
divided into two types, grant types to allow what “flows” a client is allowed, and token types that define what a client
is allowed to do with obtained tokens, such as introspecting them.
OpenID Connect defines a set of flows referred to as hybrid flows. These are not entirely new flows but rather, as the
name suggests, combinations of available flows such as authorization code and implicit. These are not defined as
separate capabilities in Curity, but will automatically be allowed if OpenID Connect is enabled and the capabilities
involved are allowed separately. To continue with the example, if both authorization code and implicit are
configured to be allowed capabilities for a client, OpenID Connect is allowed on the profile and the client is granted
the openid scope, then hybrid flows such as token code id_token will be allowed automatically.
token code id_token
OAuth clients that require user authentication may be configured with the following properties:
Client authentication is the process of a client providing credentials such that the OAuth Profile can confirm the identity of that client (i.e. client_id).
The simplest way to do it is to use a Client Secret. More advanced authentication methods are also available in
the form of Client Assertion’s, which is JWT’s signed by the client with a signature recognizable by the server.
Note that in configuration (client-authentication), client secret authentication (named basic-and-form-post) is
enabled by default, while asymmetric algorithms needs to be enabled before client assertion tokens can be used for
client authentication. See section on Client Assertion for more info on configuration and setup of that.
Client authentication using Client Secret can be done either through the “Authorization” request header, or through form-encoded parameters. Note that if both mechanisms are providing credentials, the “Authorization” header credentials are preferred and the credentials from the POST-body data are ignored.
To authenticate a client through the Authorization request header, the client_id and password need to be encoded and provided as the value of the Authorization header. Encoding is the process of concatenating the client_id and client_secret with a “:” character between them, and base64-encode the result.
When the client_id is ‘client-one’ and the client_secret is ‘nobodyknows’, then first the values need to be concatenated with “:” character:
Now the base64 encoded string of that becomes:
In the request header, this translates the following header:
POST /token HTTP/1.1
Authorization: Basic bXktY2xpZW50Om5vYm9keWtub3dz
If passing client credentials through the Authorize-header is not an option, the post-body can also be used to do so. To support this, the HTTP Request must be a POST-request with a correctly encoded content type (“application/x-www-form-urlencoded”). The body must then contain the plain client_id and client_secret parameters.
POST /token HTTP/1.1
Instead of authenticating with a client ID and secret, a client can be configured to authenticate with JWT, signed
with an asymmetric key (a private RSA key, where the public key is stored in a keystore known to Curity). In the following
example, an asymmetric key will be used for signing the JWT.
Ensure that at least one signature-algorithm is selected for client-authentication in the configuration to allow
for asymmetric algorithms like RS256 to be used for client authentication. When allowing JWT’s to be used for client
authentication, two options for configuration emerge under the node aptly named using-jwt. If
enforce-unique-jti-values is set the jti (JWT ID) value of each JWT sent will be checked and authentication
denied if Curity has seen the same jti being used before. This ensures that client assertion JWT’s must be used as one
off tokens. While a very good practice, as this might be quite cumbersome for the client this setting is disabled by
default. Setting the clock-skew allows for some difference in time between the signing client and Curity. The default
of 10 seconds should be enough for most cases, but adjust if needed.
Using the asymmetric-key setting on our client, we can point to a public key (signature verification key) stored
by Curity. The private key used for signing does not have to be available to anyone but the client. Note that the algorithm
used must correspond with the one defined in the JWT header (see example below).
Both the sub (subject) and the iss (issuer) claim must correspond to the client ID of the authenticating
client. The aud (audience) claim is the receiver of the token and should be that of a configured token endpoint in
Curity or the Curity server issuer. The jti is the ID of the token and should preferably be unique
(see Server configuration above for how to enforce this), but could be any value. Last,
the exp (expires) claim defines when the token should no longer be considered valid (seconds since epoch).
The JWT is now signed with a private key for which Curity has the corresponding public key stored in its keystore and
referenced by the client (which in the example above would be client-one).
The client assertion JWT is now ready to be used at an endpoint that would normally accept client credentials, such as
the token, introspection or revocation endpoints. An example request could look something like this:
POST /oauth/v2/token HTTP/1.1
eyJpc3Mi[...omitted for brevity...].
cC4hiUPo[...omitted for brevity...]
More information on client assertion JWT’s can be found in the OpenID Connect specification on Client Authentication
as well as RFC 7253 (note however that Curity does not implement the latter specification in it’s entirety).
It is also possible to define an optional secondary client authentication method, used only if the request failed client authentication using the primary method.
This secondary method is useful for achieving high availability even during client credential rotations or authentication method upgrades.
When defining a secondary method it is also possible to define an associated expiry date, after which the secondary method will not be usable.
To integrate the OAuth token issuance process, the Token Service offers specific capabilities to allow its user screens
to be embedded through IFRAMEs. While the default behaviour of HTML-pages is to not be allowed to be framed (due to
security reasons, i.e. clickjacking prevention), it is however possible to allow framing on a per-client base.
The configuration and use of framability controls for OAuth clients is the same as for Service Providers. Please see
Framable User Interface of Service Providers for further instructions.
To configure an OAuth-client to be framable from https://outer.example.com/main, ensure that the client’s
allowed-origins contains at least this value, i.e.
The flows that use the front channel rely on browser redirects to report a result from Curity Identity Server back to the client, for
example the code flow uses a redirect to return the authorization code, and the implicit or hybrid flows return tokens
through the redirect URI. For this, a client is configured with one or more allowed redirect URI’s that Curity Identity Server can use. A
client can, or sometimes _must_, provide the redirect URI in a request.
When a redirect URI is received, it is validated against a client’s preconfigured (or a dynamically registered client’s
pre-registered) allowed redirect URIs. An exact match is always accepted, but some validation rules may be explicitly
circumvented under specific conditions.
Redirect URI validation policies define a set of rules that are used to determine whether a provided redirect URI is
acceptable with respect to what is allowed by configuration.
A policy can specify some validation rules to be omitted or loosened up. A number of rules are only applicable to
authenticated requests, where it is possible to authenticate the client or the authenticity and integrity of the
request parameters. This is the case for Pushed Authorization Requests and JWT Secured Authorization Request (JAR).
Multiple Redirect URI validation policies can be configured for an OAuth profile, where one policy is set as default.
The default policy is used to validate the redirect URI that a client uses, unless the client is configured to use
another redirect URI validation policy. For dynamically registered clients, either the profile’s default validation
policy is used, or the one validation policy that is configured for non-templatized DCR settings is used for all
non-templatized DCR clients.
Redirect URI validation policies will only be available when validate-port-on-loopback-interfaces is enabled and allow-per-request-redirect-uris are disabled, which is the case by default.
By default, the port on loopback interfaces (e.g. localhost or 127.0.0.1) is part of the validation rules.
This can be overridden on a per-client basis, such that the client is allowed to vary the port whenever the redirection
takes place to an address that is resolved on the loopback interface.
When using Pushed Authorization Requests, there is an option to allow redirect URIs for the same origin,
i.e. a client is allowed to provide a redirect URI that matches a configured allowed URI’s scheme and host part only.
The options to configure validate-port-on-loopback-interfaces and allow-per-request-redirect-uris are deprecated in favour of Redirect URI validation policies. Until they are removed from Curity, it is not possible to use these two settings at the same time with Redirect URI validation policies. In order to use Redirect URI validation policies, the validate-port-on-loopback-interfaces option must be _enabled_ and the allow-per-request-redirect-uris option must be _disabled_, on the profile, DCR and client settings.