How to add extra properties to an access token

How to add extra properties to an access token

Preface

On receiving API requests (with access tokens) from clients, resource servers determine if the requests are allowed, and how to process them, by referring information associated with the tokens. Typical kinds of information include the following: status of the token (active / expired), who (resource owner) granted what access (scope) to whom (client). In some cases, the resource servers need to obtain other related information from an authorization server.

Authlete enables an authorization server to associate arbitrary properties with either an access token or authorization code. The authorization server can easily share the properties with resource servers so that they can consume such information for its authorization enforcement as well as making a response.

You can prevent unnecessary information disclosure as the sharing of properties can be achieved by not using clients as an intermediary.

Use cases

1. Controlling a money transfer API

Let’s assume you would like to develop a money transfer API that can process specific transaction like “send $50 to ABC shop.”

You could implement such function by creating a “send-50dollar-to-abcshop” scope, but it hardly works as you would have to prepare a lot of scopes that are multiplied with recipients and amounts.

With the properties feature of Authlete, The authorization server can associate the money transfer information (or its handle, if database manages the actual information) with an access token to be issued to a client. The resource server, which hosts the money transfer API, receives an API request with the access token from the client, asks Authlete’s introspection API to provide the properties along with details of the token, and then determines if the money transfer request is allowed to proceed.

extra-properties-money-transfer

2. Role based access control

When a resource server receives an API request with an access token, it would like to know details of the token, not only user identifier but also groups and roles of the user.

A simple solution is, that the resource server makes an introspection request to Authlete, gets the user identifier (“subject”) and makes a query to another database to find such groups/roles information.

Again, Authlete’s properties feature makes the implementation simpler. The authorization server can associate the groups/roles with the access token to be provided to the client, and the resource server can find the values from the access token included in an API request from the client. The resource server doesn’t need to communicate with the database.

extra-properties-rbac

How it works

This section describes examples on how to set and get properties.

extra-properties_1
Extra Properties

“Property” data type

Authlete defines Property data type that represents an arbitrary set of attributes associated with either an access token or an authorization code. The Property data type is a JSON object that contains the following entries.

Name Type Description
key string A key of the property
value string A value of the property
hidden boolean A flag that indicates if the property is hidden from clients
  • true: hidden from clients
  • false: not hidden from clients i.e. they can see the content |

For example, a property whose key and value are example_key and example_value respectively and that is not hidden from clients would be represented as a  JSON object as follows.

{
    "key": "example_key",
    "value": "example_value",
    "hidden": false
}

Associating properties

Associating properties with an access token and/or an authorization code will be done by an authorization server at the following steps.

Providing an authorization code and/or an access token through its authorization endpoint

An authorization server sets properties to a request to Authlete’s /auth/authorization/issue API. Authlete associates the properties with the new authorization code / the access token and provide content of a token response including the code / the token.

The following is an example using curl. (folded for readability)

  • Request
curl -s -X POST .../auth/authorization/issue \
     -u ...:... \
     -H 'Content-type: application/json' \
     -d '{"subject":"<subject>",
          "ticket":"<ticket>",
          "properties":[
              {"key":"example\_key", "value":"example\_value", "hidden":true}
          ]
     }'
  • Response
{
    "type": "authorizationIssueResponse",
    "resultCode": "A040001",
    "resultMessage": "[A040001] The authorization request was processed successfully.",
    "accessTokenDuration": 0,
    "accessTokenExpiresAt": 0,
    "action": "LOCATION",
    "authorizationCode": "...",
    "responseContent": "https://client.example.org/cb/example.com?code=..."
}

You can implement this operation with authlete-java-jaxrs library. Specifically there is a getProperties method in AuthorizationDecisionHandlerSpiAdapter class, that handles association of properties (returns null by default).

Providing an access token through a token endpoint

An authorization server sets properties to a request to Authlete’s /auth/token API. Authlete associates the properties with the new access token and provide content of a token response including the token.

The following is an example using curl. (folded for readability)

  • Request
curl -s -X POST .../auth/token \
   -u ...:... \
   -H 'Content-type: application/json' \
   -d '{
        "clientId": "<clientId>",
        "clientSecret": "<clientSecret>",
        "parameters": "redirect_uri=https://client.example.org/cb/example.com&grant_type=authorization_code&code=...",
        "properties": [
            {"key": "example_key", "value": "example_value", "hidden": false}
        ]
    }'
  • Response
{
  "type": "tokenResponse",
  "resultCode": "A050001",
  "resultMessage":
    "[A050001] The token request (grant_type=authorization_code) was processed
     successfully.",
  "accessToken": "...",
  "action": "OK",
...
  "properties": [
    {
      "hidden": false,
      "key": "example_key",
      "value": "example_value"
    }
  ],
  "refreshToken": "...",
  "responseContent":
    "{\"access_token\":\"...\",
      \"refresh_token\":\"...\",
      \"scope\":\"payment\",
      \"token_type\":\"Bearer\",
      \"expires_in\":300,
      \"example_key\":\"example_value\"
     }",
  "subject": "<subject>"
}

In this case, the property is exposed to the client as "hidden":false is set. Client can see the property as a part of a token response and/or a part of payload of JWT-formatted access token (if used). This value must be set to true if the property is only for resource servers i.e. clients must not see it.

Obtaining properties

By sending an access token (extracted from an API request from a client) to Authlete’s /auth/introspection API, an resource server receives a response that would contain properties.

The following is an example using curl. (folded for readability)

  • Request
curl -s -X POST \
.../auth/introspection \
-u ...:... \
-H 'Content-type: application/json' \
-d '{"token":"<accessToken>"}'
  • Response
{
    "clientId": <clientId>,
    "properties": [
        {
            "key": "example_key",
            "value": "example_value",
            "hidden": false
        }
    ],
    "action": "OK",
    "resultCode": "A056001",
    "expiresAt": 1565847795000,
    "subject": "<subject>",
    "type": "introspectionResponse",
    "refreshable": true,
    "usable": true,
    "existent": true,
    "resultMessage": "[A056001] The access token is valid.",
    "responseContent": "Bearer error=\"invalid_request\""
    ...

}

Notes

Reserved values for “key”

The following values are not applicable for “key” of properties, as RFC 6749 and OpenID Connect Core 1.0 have reserved the names for parameters which may be included in a response from an authorization server. Authlete discards them if they are specified.

  • access_token
  • token_type
  • expires_in
  • refresh_token
  • scope
  • error
  • error_description
  • error_uri
  • id_token

Type of “value”

String is the only allowed type of “value.” Neither boolean nor array can be specified.

Size of properties

Size of properties is limited. Properties are saved into the database on the server side after going through the steps described below.

  1. Converted to a two-dimensional array (e.g. [[“example_parameter”,“example_value”,null]]). The value of hidden is converted to either null or an empty string. They mean false and true, respectively.
  2. Converted to JSON (e.g. “[["example_parameter":"example_value",null]]”)
  3. Encrypted by AES/CBC/PKCS5Padding
  4. Encoded by base64url
  5. If the length of the resultant base64url string generated by the above steps exceeds 65535, an error occurs.

See also