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.

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