There are two use cases for introspection :
  1. An application which has received an access_token or a refresh_token and needs to get metadata information about these tokens (when they were issued, the scopes, ...). This is not the primary use case for introspection.
  2. During a ProtectedResource access request, a ResourceServer receives an access_token which it needs to validate.
The principle used by CYM-Identity is to always generate the proper access_token for each ProtectedResource request, through the resource parameter in the Authorization request, Authorization Code request or the Refresh Token request. Unfotunately, the ResourceServer may need more information about the access_token than what is directly available in the access_token. Enters the introspection flow.

Resource Server - access_token introspection

By default, CYM-Identity uses self-contained (JWT) access_tokens which can be verified and validated locally by the ResourceServer. For privacy reasons, it's not recommended to include user claims in access_tokens. In fact by adding, personal information in a JWT, the Application will have access to this data without having an explicit consent from the user or from your administrator.
The introspection_endpoint can be used to share additional claims with ResourceServers, with the added security of having the ResourceServer authenticate before accessing the data.

Introspection request

POST /token_endpoint HTTP/1.1
Host: oauth.server
Content-Type: application/x-www-form-urlencoded
token=AN_ACCESS_TOKEN_VALUE
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
ParameterRequiredDescription
tokenYesThe access_token to be introspected
token_type_hintNoAn indication to the OAuth Provider the type of token. Possible values are access_token or refresh_token
client_idYesThe identifier for the ResourceServer
client_secretNoOnly required if the ResourceServer authenticates through client_secret_post
client_assertionNoOnly required if the ResourceServer authenticated through client_secret_jwt or private_key_jwt
client_assertion_typeNoOnly required if a client_assertion is used. The value must be urn:ietf:params:oauth:client-assertion-type:jwt-bearer

Introspection response

Error response

The following error is returned when the ResourceServer client_credentials validation fails or the request is malformed
HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"error": "AN_ERROR_CODE",
"error_description": "AN_ERROR_DESCRIPTION"
}

The following response is returned if the ResourceServer is not the aud of the access_token, the token has expired, the token is unknown, or the token is not an access_token
HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"active": false
}

Successful response

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"sub": "SUBJECT_IDENTIFIER",
"resource": "https://resource.server.com/protected/resource",
"aud": "ACCESS_TOKEN_AUDIENCE",
"nbf": 1607870056,
"iat": 1607870056,
"exp": 1607873656,
"scope": "SPACE_SEPARATED_SCOPES",
"client_id": "ACCESS_TOKEN_CLIENT_ID",
"active": true
}
In case the ResourceServer has been assigned scopes which are linked to claims, the response will include the claims. Example for a ResourceServer which has the profile scope
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"updated_at": 1607850283,
"locale": "en_US",
"zoneinfo": "Europe/Berlin",
"birthdate": null,
"gender": null,
"picture": "https://user.as.com/picture",
"profile": "https://user.as.com/profile/USER_ID",
"preferred_username": "username@example.com",
"nickname": "nick-name",
"middle_name": null,
"given_name": "Nick",
"family_name": "Name",
"name": "Nick Name",
"sub": "SUBJECT_IDENTIFIER",
"resource": "https://resource.server.com/protected/resource",
"aud": "ACCESS_TOKEN_AUDIENCE",
"nbf": 1607870056,
"iat": 1607870056,
"exp": 1607873656,
"scope": "SPACE_SEPARATED_SCOPES",
"client_id": "ACCESS_TOKEN_CLIENT_ID",
"active": true
}