OAuth Client Configuration

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.

Tip

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 REST CONF.

Client Capabilities

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.

Capability Type Description
authorization-code Grant type Allows Authorization Code Grant
implicit Grant type Allows Implicit Grant
resource-owner-password-credentials Grant type Allows Resource Owner Password Credentials Grant
client_credentials Grant type Allows Client Credentials Grant
assisted-token Grant type Allows Assisted Token Grant
ciba Grant type Allows Backchannel Authentication Grant
introspection Token Allows Token Introspection
token-exchange Token Allows Token Exchange
device-flow Token Allows Device Flow.

Hybrid Capabilities

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.

User Authentication

OAuth clients that require user authentication may be configured with the following properties:

Parameter Name Mandatory Description
allowed-authenticators No the authenticators to be used by this client (reference by ID). If not set, all authenticators are allowed.
authenticator-filters No any Authenticator Filters to be used by this client.
template-area No allows specifying The Template Override System to override some (or all) templates being used.
required-claim No a mandatory claim
context-info No a message that can be shown to users during authentication.
force-authn No whether user authentication is forced at all times.
freshness No maximum age in seconds after which re-authentication must take place.
allowed-origins No list of URIs or URI-patterns that is allowed to embed the rendered pages inside an iframe or be a trusted source. See Framable User Interface for details.

Client Authentication

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 Secret

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.

Authorization Request Header

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.

Example:

When the client_id is ‘client-one’ and the client_secret is ‘nobodyknows’, then first the values need to be concatenated with “:” character:

client-one:nobodyknows

Now the base64 encoded string of that becomes:

bXktY2xpZW50Om5vYm9keWtub3dz

In the request header, this translates the following header:

POST /token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: example.curity.se
Authorization: Basic bXktY2xpZW50Om5vYm9keWtub3dz

Post-body

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.

Example:

POST /token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: example.curity.se

client_id=client-one&client_secret=nobodyknows

Client Assertion

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.

Server configuration

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.

Client configuration

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).

Example client assertion JWT

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).

JWT header

{
    "alg": "RS256",
    "typ": "JWT"
}

JWT body

{
    "sub": "client-one",
    "iss": "client-one",
    "aud": "https://curity.example.org/oauth/v2/token",
    "jti": "958af185-2bb8-4a08-be87-3f89138c0b6e",
    "exp": 1511801974
}

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
Host: curity.example.org
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4&
client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3A
client-assertion-type%3Ajwt-bearer&
client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6IjIyIn0.
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).

Secondary authentication

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.

  • Example: update client secret from S1 to S2.
    1. Configuration administrator changes secret from S1 to S2 on the primary method and creates a secondary method using the S1 secret. This ensures that both S1 and S2 will be usable simultaneously.
    2. Client stops using S1 and starts using S2.
    3. Configuration administrator removes the secondary method.
  • Example: update client from using secret S1 to use client assertions with key K1.
    1. Configuration administrator changes primary authentication from secret S1 to client assertion susing key K1. In the same configuration change, she also creates a secondary method using the S1 secret, allowing both methods to be used simultaneously.
    2. Client stops using S1 secret and starts using client assertions with key K1.
    3. Configuration administrator removes the secondary method.

When defining a secondary method it is also possible to define an associated expiry date, after which the secondary method will not be usable.

Client Framability

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.

Examples

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.

...
      <client-store>
        <config-backed>
          <client>
            <id>client-one</id>
            ...
            <allowed-origins>https://outer.example.com</allowed-origins>
            ...
          </client>
        </config-backed>
      </client-store>
...

Redirect URI validation

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.

Validation policies

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.

Note

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.

Using Validate Port on Loopback Interfaces and Allow Per Request Redirect URIs (deprecated)

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.

Important

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.