OAuth 2.0 client credentials grant support

Posted 2014-08-29

The upcoming 2.0 release of the Connect2id Server will support OAuth 2.0 client credential grants. This grant is intended for client apps that act on their own behalf (instead on the behalf of an end-user, the common OAuth 2.0 case), to make requests to protected web APIs and other resources with a simple OAuth access token.

Registering a client credentials grant app

Before a client app can receive access tokens from the Connect2id Server it must be registered first. This is done by a posting a simple JSON object to the standard client registration endpoint of the server.

To register a client app for the client credentials grant:

POST /client-reg HTTP/1.1
Host: c2id.com
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
Content-Type: application/json

{
 "client_name"    : "My House App",
 "grant_types"    : [ "client_credentials" ],
 "response_types" : [ ],
 "scope"          : "access_cam read_thermostat set_thermostat"
}

Alternatively, you can update an existing client registration to include the client_credentials grant.

The scope parameter is important - it specifies the authorised scope values for the client app, which the protected resource should understand. Access token requests for values that are not in this whitelist will be denied.

Upon successful registration with the Connect2id Server the client app will be issued a client_id and a client_secret. These must be recorded by the app, to be passed with subsequent requests for an access token to the Connect2id Server.

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
  "client_id"                  : "yfwkw4qlmhv4q",
  "client_id_issued_at"        : 1409314987,
  "client_secret"              : "2Ua4B5sFXfgzMytywQjOMc5K1bjVyxWytrIWlNjPnWw",
  "client_secret_expires_at"   : 0,
  "application_type"           : "web",
  "scope"                      : "access_cam read_thermostat set_thermostat",
  "token_endpoint_auth_method" : "client_secret_basic",
  "registration_client_uri"    : "http://localhost:8080/c2id/client-reg/yfwkw4qlmhv4q",
  "registration_access_token"  : "Qpios-RCEimdrz4ABcKDBojc6C_FWPkFtlW8v9eykrM",
  "grant_types"                : [ "client_credentials" ],
  "response_types"             : [ ]
}

Requesting an access token for the client app

To get an access token for the client app you need to make an OAuth 2.0 request to the token endpoint of the Connect2id Server.

You need the following details to compose the token request:

  • The token endpoint URL of the Connect2id server. It can be obtained from the public OpenID Connect provider metadata, available at http://[server-host]/.well-known/openid-configuration
  • The client ID and secret to compose the HTTP basic authentication header.
  • The requested scope values. If the scope parameter is omitted, the server will treat this as a request for all registered scope values for the client.

This is how the request should look like:

POST /token HTTP/1.1
Host: localhost:8080
Authorization: Basic eWZ3a3c0cWxtaHY0cToyVWE0QjVzRlhmZ3pNeXR5d1FqT01jNUsxYmpWeXhXeXRySVdsTmpQbld3\
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials

A successful access token response will like this:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
 "token_type"    : "Bearer",
 "access_token"  : "eyJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJzY3AiOlsib3BlbmlkIiw...",
 "expires_in"    : 3600,
 "scope"         : "access_cam read_thermostat set_thermostat"
}

Note that with the client credentials grant a refresh token is not issued. If the obtained access token has expired, the client app should simply repeat the request and get a new one.

If the client authentication has failed the Connect2id Server will return an HTTP error status, and no access token will be issued.

HTTP/1.1 HTTP 401 Unauthorized
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
 "error"             : "invalid_client",
 "error_description" : "Client authentication failed"
}

Devising your own authorisation logic

The Connect2id Server comes with a simple client credentials grant handler that uses the registered scope parameters for the client to determine the authorised scope for it. That will probably be sufficient for most business cases.

For customers who wish to plug in their own custom authorisation logic, we've provided them with a Java SPI for handling client credentials grants, part of a comprehensive toolkit for developing Connect2id server extensions:

https://bitbucket.org/connect2id/server-sdk/src

One particular implementation of the client credentials SPI allows the authorisation logic to be provided by an external web service, addressable by means of a simple RESTful API:

https://bitbucket.org/connect2id/client-credentials-grant-web-api

The key benefit of using an external web service to handle the grant authorisations is that you can leverage your preferred web framework for that, while enabling changes of the authorisation logic on the fly (to install an updated SPI module into the Connect2id Server you will need to restart it).

Our support team is available

Questions? Feel free to post a comment below, or get in touch with Connect2id support.