Add an OAuth 2.0 authentication layer with the Authorization Code Grant, Client Credentials, Implicit Grant or Resource Owner Password Credentials Grant flow. This plugin requires the SSL Plugin with the only_https parameter set to true to be already installed on the API, failing to do so will result in a security weakness.


Configuration

Configuring the plugin is straightforward, you can add it on top of an API by executing the following request on your Kong server:

$ curl -X POST http://kong:8001/apis/{api}/plugins \
    --data "name=oauth2" \
    --data "config.enable_authorization_code=true" \
    --data "config.scopes=email,phone,address" \
    --data "config.mandatory_scope=true"

api: The id or name of the API that this plugin configuration will target.

You can also apply it for every API using the http://kong:8001/plugins/ endpoint. Read the Plugin Reference for more information.

form parameter default description
name The name of the plugin to use, in this case: oauth2
config.scopes Describes an array of comma separated scope names that will be available to the end user
config.mandatory_scope
optional
false An optional boolean value telling the plugin to require at least one scope to be authorized by the end user
config.token_expiration
optional
7200 An optional integer value telling the plugin how long should a token last, after which the client will need to refresh the token. Set to 0 to disable the expiration.
config.enable_authorization_code
optional
false An optional boolean value to enable the three-legged Authorization Code flow (RFC 6742 Section 4.1)
config.enable_client_credentials
optional
false An optional boolean value to enable the Client Credentials Grant flow (RFC 6742 Section 4.4)
config.enable_implicit_grant
optional
false An optional boolean value to enable the Implicit Grant flow which allows to provision a token as a result of the authorization process (RFC 6742 Section 4.2)
config.enable_password_grant
optional
false An optional boolean value to enable the Resource Owner Password Credentials Grant flow (RFC 6742 Section 4.3)
config.hide_credentials
optional
false An optional boolean value telling the plugin to hide the credential to the upstream API server. It will be removed by Kong before proxying the request
config.accept_http_if_already_terminated
optional
false Accepts HTTPs requests that have already been terminated by a proxy or load balancer and the x-forwarded-proto: https header has been added to the request. Only enable this option if the Kong server cannot be publicly accessed and the only entry-point is such proxy or load balancer.

Usage

In order to use the plugin, you first need to create a consumer to associate one or more credentials to. The Consumer represents a developer using the final service/API.

Endpoints

By default the OAuth 2.0 plugin listens on the following endpoints when consuming the API on the proxy port:

Endpoint description
/oauth2/authorize The endpoint to the Authorization Server that provisions authorization codes for the Authorization Code flow, or the access token when the Implicit Grant flow is enabled. Only POST is supported.
/oauth2/token The endpoint to the Authorization Server that provision access tokens. This is also the only endpoint to use for the Client Credentials and Resource Owner Password Credentials Grant flows. Only POST is supported.

The clients trying to authorize and request access tokens must use these endpoints. Remember that the endpoints above must be combined with the right URI path or headers that you normally use when consuming the root / endpoint of the API through Kong.

Create a Consumer

You need to associate a credential to an existing Consumer object, that represents a user consuming the API. To create a Consumer you can execute the following request:

$ curl -X POST http://kong:8001/consumers/ \
    --data "username=user123" \
    --data "custom_id=SOME_CUSTOM_ID"
parameter default description
username
semi-optional
The username of the consumer. Either this field or custom_id must be specified.
custom_id
semi-optional
A custom identifier used to map the consumer to another database. Either this field or username must be specified.

A Consumer can have many credentials.

Create an Application

Then you can finally provision new OAuth 2.0 credentials (also called "OAuth applications") by making the following HTTP request:

$ curl -X POST http://kong:8001/consumers/{consumer_id}/oauth2 \
    --data "name=Test%20Application" \
    --data "client_id=SOME-CLIENT-ID" \
    --data "client_secret=SOME-CLIENT-SECRET" \
    --data "redirect_uri=http://some-domain/endpoint/"

consumer_id: The Consumer entity to associate the credentials to

form parameter default description
name The name to associate to the credential. In OAuth 2.0 this would be the application name.
client_id
optional
You can optionally set your own unique client_id. If missing, the plugin will generate one.
client_secret
optional
You can optionally set your own unique client_secret. If missing, the plugin will generate one.
redirect_uri The URL in your app where users will be sent after authorization (RFC 6742 Section 3.1.2)

Migrating Access Tokens

If you are migrating your existing OAuth 2.0 applications and access tokens over to Kong, then you can:

  • Migrate consumers and applications by creating OAuth 2.0 applications as explained above.
  • Migrate access tokens using the /oauth2_tokens endpoints in the Kong's Admin API. For example:
$ curl -X POST http://kong:8001/oauth2_tokens \
    --data "credential_id=KONG-APPLICATION-ID" \
    --data "token_type=bearer" \
    --data "access_token=SOME-TOKEN" \
    --data "refresh_token=SOME-TOKEN" \
    --data "expires_in=3600"
form parameter default description
credential_id The ID of the OAuth 2.0 application created on Kong.
token_type
optional
bearer The token type.
access_token
optional
You can optionally set your own access token value, otherwise a random string will be generated.
refresh_token
optional
You can optionally set your own refresh token value, otherwise a random string will be generated.
expires_in The expiration time (in seconds) of the access token.
scope
optional
The authorized scope associated with the token.
authenticated_userid
optional
The custom ID of the user who authorized the application.

Upstream Headers

When a client has been authenticated and authorized, the plugin will append some headers to the request before proxying it to the upstream API/Microservice, so that you can identify the consumer and the end-user in your code:

  • X-Consumer-ID, the ID of the Consumer on Kong
  • X-Consumer-Custom-ID, the custom_id of the Consumer (if set)
  • X-Consumer-Username, the username of the Consumer (if set)
  • X-Authenticated-Scope, the comma-separated list of scopes that the end user has authenticated (if available)
  • X-Authenticated-Userid, the logged-in user ID who has granted permission to the client

You can use this information on your side to implement additional logic. You can use the X-Consumer-ID value to query the Kong Admin API and retrieve more information about the Consumer.


OAuth 2.0 Flows

Client Credentials

The Client Credentials flow will work out of the box, without building any authorization page. The clients will need to use the /oauth2/token endpoint to request an access token.

Authorization Code

After provisioning Consumers and associating OAuth 2.0 credentials to them, it is important to understand how the OAuth 2.0 authorization flow works. As opposed to most of the Kong plugins, the OAuth 2.0 plugin requires some little additional work on your side to make everything work well:

  • You must implement an authorization page on your web application, that will talk with the plugin server-side.
  • Optionally you need to explain on your website/documentation how to consume your OAuth 2.0 protected services, so that developers accessing your service know how to build their client implementations

The flow explained

Building the authorization page is going to be the primary task that the plugin itself cannot do out of the box, because it requires to check that the user is properly logged in, and this operation is strongly tied with your authentication implementation.

The authorization page is made of two parts:

  • The frontend page that the user will see, and that will allow him to authorize the client application to access his data
  • The backend that will process the HTML form displayed in the frontend, that will talk with the OAuth 2.0 plugin on Kong, and that will ultimately redirect the user to a third party URL.

A diagram repreenting this flow:

  1. The client application will redirect the end user to the authorization page on your web application, passing client_id, response_type and scope (if required) as querystring parameters. This is a sample authorization page:

  2. Before showing the actual authorization page, the web application will make sure that the user is logged in.

  3. The client application will send the client_id in the querystring, from which the web application can retrieve both the OAuth 2.0 application name, and developer name, by making the following request to Kong:

    $ curl kong:8001/oauth2?client_id=XXX
    
  4. If the end user authorized the application, the form will submit the data to your backend with a POST request, sending the client_id, response_type and scope parameters that were placed in <input type="hidden" .. /> fields.

  5. The backend must add the provision_key and authenticated_userid parameters to the client_id, response_type and scope parameters and it will make a POST request to Kong at your API address, on the /oauth2/authorize endpoint. If an Authorization header has been sent by the client, that must be added too. The equivalent of:

    $ curl https://your.api.com/oauth2/authorize \
        --header "Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW" \
        --data "client_id=XXX" \
        --data "response_type=XXX" \
        --data "scope=XXX" \
        --data "provision_key=XXX" \
        --data "authenticated_userid=XXX"
    

    The provision_key is the key the plugin has generated when it has been added to the API, while authenticated_userid is the ID of the logged-in end user who has granted the permission.

  6. Kong will respond with a JSON response:

    {
      "redirect_uri": "http://some/url"
    }
    

    With either a 200 OK or 400 Bad Request response code depending if the request was successful or not.

  7. In both cases, ignore the response status code and just redirect the user to whatever URI is being returned in the redirect_uri property.

  8. The client appication will take it from here, and will continue the flow with Kong with no other interaction with your web application. Like exchaging the authorization code for an access token if it's an Authorization Code Grant flow.

  9. Once the Access Token has been retrieved, the client application will make requests on behalf of the user to your final API.

  10. Access Tokens can expire, and when that happens the client application needs to renew the Access Token with Kong and retreive a new one.

In this flow, the steps that you need to implement are:

  • The login page, you probably already have it (step 2)
  • The Authorization page, with its backend that will simply collect the values, make a POST request to Kong and redirect the user to whatever URL Kong has returned (steps 3 to 7).

Resource Owner Password Credentials

The Resource Owner Password Credentials Grant is a much simpler version of the Authorization Code flow, but it still requires to build an authorization backend (without the frontend) in order to make it work properly.

OAuth 2.0 Flow

  1. On the first request, the client application make a request including some OAuth2 parameters, including username and password parameters, to your web-application.

  2. The backend of your web-application will authenticate the username and password sent by the client, and if successful will add the provision_key and authenticated_userid parameters to the parameters originally sent by the client, and it will make a POST request to Kong at your API address, on the /oauth2/token endpoint. If an Authorization header has been sent by the client, that must be added too. The equivalent of:

    $ curl https://your.api.com/oauth2/token \
        --header "Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW" \
        --data "client_id=XXX" \
        --data "client_secret=XXX" \
        --data "scope=XXX" \
        --data "provision_key=XXX" \
        --data "authenticated_userid=XXX" \
        --data "username=XXX" \
        --data "password=XXX"
    

    The provision_key is the key the plugin has generated when it has been added to the API, while authenticated_userid is the ID of the end user whose username and password belong to.

  3. Kong will respond with a JSON response

  4. The JSON response sent by Kong must be sent back to the original client as it is. If the operation is successful, this response will include an access token, otherwise it will include an error.

In this flow, the steps that you need to implement are:

  • The backend endpoint that will process the original request and will authenticate the username and password values sent by the client, and if the authentication is successful, make the request to Kong and return back to the client whatever response Kong has sent back.

Refresh Token

When your access token expires, you can generate a new access token using the refresh token you received in conjunction to your expired access token.

$ curl -X POST https://your.api.com/oauth2/token \
    --data "grant_type=refresh_token" \
    --data "client_id=XXX" \
    --data "client_secret=XXX" \
    --data "refresh_token=XXX"