Token introspection
1. Inspecting identifier-based access tokens
When an OAuth 2.0 secured resource server receives a request from a client it needs to validate the included access token. Only then can the request proceed.
The token introspection (RFC 7662) endpoint of the Connect2id server is where identifier-based access tokens get validated. Those are long expiring keys referencing authorisations stored in the server. Identifier-based tokens are useful in applications where token and client revocation must have an immediate effect.
Self-contained (JWT-encoded) access tokens, designed for local validation at the resource server by checking their digital signature, can also be inspected at this endpoint.
The introspection endpoint of the Connect2id server can optionally return JWT-secured responses, to meet assurance and legal requirements for applications dealing with verified person data, certificates and qualified electronic signatures.
Note: Tokens can also be inspected at a Connect2id specific authorisation store API.
2. The token introspection URL
It is advertised in the introspection_endpoint
server
metadata and has this form:
[issuer-url]/token/introspect
3. Prerequisites
3.1 Access
Requests to the introspection endpoint must be either authenticated with client credentials or authorised with a bearer access token.
3.1.1 Authenticated requests
This is the simplest and recommended approach. The resource server
authenticates at the token introspection endpoint with the registered
method,
set by the token_endpoint_auth_method
metadata parameter.
To this end the resource server must be registered as
an OAuth 2.0 client for the client_credentials
grant type (i.e. as a client
acting on its own behalf), with a scope
parameter including the URI of the
introspection endpoint, e.g. https://c2id.com/token/introspect
, or the URI
urn:c2id:introspection_endpoint
.
Example client registration request for a resource server:
POST /clients HTTP/1.1
Host: c2id.com
Authorization: Bearer ztucZS1ZyFKgh0tUEruUtiSTXhnexmd6
Content-Type: application/json
{
"grant_types" : [ "client_credentials" ],
"scope" : "https://c2id.com/token/introspect"
}
Example client registration response:
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"client_id" : "izad7cqy34bg4",
"client_id_issued_at" : 1448356530,
"client_secret" : "1fu9sZE56ydjzGmovEHjIDgrdYDcT5gd-gqgXwhvmS0",
"client_secret_expires_at" : 0,
"registration_client_uri" : "https://c2id.com/clients/izad7cqy34bg4",
"registration_access_token" : "1NfgTP09qheYkNR7Pj6kCUVAp3gW-el0Ka9-U3Emu7Q.Kg",
"grant_types" : [ "client_credentials" ],
"response_types" : [ ],
"token_endpoint_auth_method" : "client_secret_basic",
"scope" : "https://c2id.com/token/introspect"
}
The client above registered for basic authentication with client_id
and
client_secret
. More secure authentication methods, such as private_key_jwt
and self_signed_tls_client_auth
, are available, and should be considered for
resource servers dealing with important data.
Upon receiving a token introspection request the
Connect2id server will validate the client credentials, and if they match a
client that is registered for the expected scope (e.g.
https://c2id.com/token/introspect
), the request will proceed.
3.1.2 Token authorised requests
This approach requires an access token with a scope value set to the URI of the
introspection endpoint, e.g. https://c2id.com/token/introspect
, to authorise
the introspection request. The token is passed in the Authorization
header of
the token introspection request.
One way to obtain such a token is to be registered for the client credentials grant and the required scope value, as explained in the previous section.
Example request for an access token using a client credentials grant:
POST /token HTTP/1.1
Host: c2id.com
Authorization: Basic aXphZDdjcXkzNGJnNDoxZnU5c1pFNTZ5ZGp6R21vdkVIaklEZ3JkWURjVDVnZC1ncWdYd2h2bVMw
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&scope=https%3A%2F%2Fc2id.com%2Ftoken%2Fintrospect
The minted access token can then be used to make introspection requests:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token" : "eyJhbGciOiJSUzI1NiIsImtpZCI6InMxIn0.eyJzY3AiOlsidG9rZW4ta...",
"token_type" : "Bearer",
"expires_in" : 600,
"scope" : "https://c2id.com/token/introspect"
}
3.2 Audience restriction and pruning
An access token with an explicit audience (aud
) is considered to be audience
restricted. Such a token can be introspected only by clients whose client_id
is found in the token aud
array; other clients will receive an introspection
response indicating the token is invalid. The server
will also remove any other client_id
values from the aud
array, unless
audience pruning is disabled.
These measures ensure the Connect2id server doesn’t leak authorisation data for a token that wasn’t intended for consumption at a resource server.
4. Web API overview
Resources | |
---|---|
Representations | Errors |
4. Resources
4.1 /token/introspect
4.1.1 POST
Inspects an access token. Inspection of refresh tokens is not supported by the Connect2id server, although they may be submitted according to RFC 7662.
The caller must authenticate or submit a bearer token authorisation.
The response can optionally be JWT-secured.
Header parameters:
-
[ Authorization ] Used for HTTP basic authentication of the client, or for bearer token authorisation.
-
Content-Type Must be set to
application/x-www-form-urlencoded
. -
[ Accept ] If set to
application/token-introspection+jwt
the response will be JWT-secured, if set toapplication/jwt
secured according to a legacy specification. -
[ Issuer ] The issuer URL when issuer aliases are configured, or the issuer URL for a tenant (in the multi-tenant Connect2id server edition). The tenant can be alternatively specified by the Tenant-ID header.
-
[ Tenant-ID ] The tenant ID (in the multi-tenant Connect2id server edition). The tenant can be alternatively specified by the Issuer header.
Body with form parameters:
-
token The token to inspect.
-
[ token_type_hint ] Optional hint about the type of the submitted token; if omitted the server will use heuristics to determine the token type:
-
access_token – the token is an access token
-
refresh_token – the token is a refresh token (not supported)
-
-
[ revoke = false] {true|false} Facilitates single use of identifier-based access tokens. Causes the access token to be automatically deleted from the store after successful inspection. Has no effect for a self-contained (JWT-encoded) access token. This is a non-standard query parameter.
Success:
- Code:
200
- Content-Type:
application/json
for a regular response,application/token-introspection+jwt
for a JWT-secured response. - Body:
- {object} A regular token introspection response, or a
- {string} JWT-secured response, if the
Accept
header was set toapplication/jwt
or if the server is configured to always respond with a JWT.
Errors:
Example token introspection request with basic authentication:
POST /token/introspect HTTP/1.1
Host: c2id.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
token=giuLtTTnya5XpHVKNopT9w.gepM14CKpHcWloJ3XqMtvA
Example request by a resource server that needs to guarantee single use of the received tokens, the revoke parameter will cause the token to be removed after inspection (applies to identifier-based tokens only, not to self-contained tokens):
POST /token/introspect HTTP/1.1
Host: c2id.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
token=giuLtTTnya5XpHVKNopT9w.gepM14CKpHcWloJ3XqMtvA&revoke=true
Example token introspection request with client secret JWT authentication:
POST /token/introspect HTTP/1.1
Host: c2id.com
Content-Type: application/x-www-form-urlencoded
token=giuLtTTnya5XpHVKNopT9w.gepM14CKpHcWloJ3XqMtvA&
client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&
client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6IjIyIn0.eyJpc3Mi...
Example token introspection request using bearer token authorisation:
POST /token/introspect HTTP/1.1
Host: c2id.com
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6InMxIn0.eyJzY3AiOlsiaHR0...
token=giuLtTTnya5XpHVKNopT9w.gepM14CKpHcWloJ3XqMtvA
The server returns a 200
status for valid as well as invalid / expired
tokens. The token validity is determined by the active
parameter in the
response body.
Example response for a valid access token:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
"active" : true,
"scope" : "https://example.com/accounts https://example.com/groups",
"client_id" : "izad7cqy34bg4",
"token_type" : "Bearer",
"exp" : 1448367412,
"iat" : 1448366912,
"sub" : "izad7cqy34bg4",
"iss" : "https://c2id.com",
"jti" : "thee5Quu"
}
For an invalid, revoked or expired token:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
"active" : false
}
5. Representations
5.1 Token introspection response
The token introspection is represented as a JSON object. The only required
member is active
, all other members are optional. The response can also
contain consented OpenID claims fed into the token via the access_token:
prefix. An SPI
enables override of the default response.
-
active {true|false} If
true
the token is valid, active and, if it has an explicit audience, the calling resource server is in it. Iffalse
the token is invalid, has been revoked, has expired or the caller (resource server) is not in its audience, in which case no further details are provided. -
[ scope ] {string} The scope values for the token.
-
[ client_id ] {string} The identifier of the OAuth 2.0 client to which the token was issued.
-
[ username ] {string} Username of the resource owner who authorised the token.
-
[ token_type ] {string} Type of the token, set to
Bearer
orDPoP
. -
[ exp ] {number} The token expiration time, as number of seconds since the Unix epoch (1970-01-01T0:0:0Z) as measured in UTC until the date/time. Has the same semantics as the standard JWT claim name.
-
[ iat ] {number} The token issue time, as number of seconds since the Unix epoch (1970-01-01T0:0:0Z) as measured in UTC until the date/time. Has the same semantics as the standard JWT claim name.
-
[ nbf ] {number} The token use-not-before time, as number of seconds since the Unix epoch (1970-01-01T0:0:0Z) as measured in UTC until the date/time. Has the same semantics as the standard JWT claim name.
-
[ sub ] {string} The subject of the token, of type public or pairwise. Typically the user identifier of the resource owner who authorised the token. Has the same semantics as the standard JWT claim name.
-
[ aud ] {string array} Audience values for the token. Has the same semantics as the standard JWT claim name. If the token has an explicit audience only the
client_id
of the introspecting client will be included, unless audience pruning is disabled. -
[ iss ] {string} The token issuer (the OpenID Provider / Authorisation Server issuer URI). Has the same semantics as the standard JWT claim name.
-
[ jti ] {string} Identifier for the token. Has the same semantics as the standard JWT claim name.
-
[ cnf.x5t#S256 ] {string} For a client X.509 certificate bound token, the BASE64URL-encoded SHA-256 thumbprint of the certificate.
-
[ cnf.jkt ] {string} For a DPoP token, the BASE64URL-encoded SHA-256 thumbprint of the client JWK.
-
[ act ] {object} The actor, in impersonation and delegation scenarios.
-
[ dat ] {object} Optional custom authorisation data.
Example introspection response for a valid token:
{
"active" : true,
"scope" : "https://example.com/accounts https://example.com/groups",
"token_type" : "Bearer",
"client_id" : "izad7cqy34bg4",
"exp" : 1448367412,
"iat" : 1448366912,
"sub" : "izad7cqy34bg4",
"iss" : "https://c2id.com",
"jti" : "daeN0Eit"
}
Example introspection response for an invalid, expired or revoked token:
{
"active" : false
}
5.2 JWT-secured token introspection response
A JWT containing an introspection response according to draft-ietf-oauth-jwt-introspection-response-12.
The JWT is signed with the same JWS algorithm and key as self-contained (JWT-encoded) access tokens.
JWT header parameters:
- alg The JWS algorithm.
- kid The JSON Web Key (JWK) identifier.
-
typ The JWT type, set to
token-introspection+jwt
, unless configured otherwise.
JWT claims:
- iss {string} The JWT issuer, set to the Connect2id server issuer URL.
-
aud {string} The JWT audience, set to the
client_id
of the token introspection caller. - iat {number} The token issue time, as number of seconds since the Unix epoch (1970-01-01T0:0:0Z) as measured in UTC until the date/time.
- token_introspection {object} The token introspection response.
5.3 Legacy JWT-secured token introspection response
A JWT containing an introspection response according to draft-ietf-oauth-jwt-introspection-response-12.
The JWT is signed with the same JWS algorithm and key as self-contained (JWT-encoded) access tokens.
JWT header parameters:
- alg The JWS algorithm.
- kid The JSON Web Key (JWK) identifier.
-
typ The JWT type, set to
token-introspection+jwt
, unless configured otherwise.
The JWT claims contain the introspection response
members as top-level claims; the iat is set to the introspection response
issue time; the aud to the client_id
of the token introspection caller;
the jti is always set and identical for all introspections for a given
token.
6. Errors
400 Bad Request
Invalid or malformed request.
Example:
HTTP/1.1 400 Bad Request
{
"error" : "invalid_request",
"error_description" : "Invalid request: Missing required token parameter"
}
401 Unauthorized
The request was denied due to an invalid or missing client authentication /
authorisation. The error_description
is a checklist of all possible causes
why the client authentication may have failed. The client_auth_id
can be used
to identify the exact
cause.
Example:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"error" : "invalid_client",
"error_description" : "Invalid client: Possible causes may be missing /
invalid client_id, missing client authentication,
invalid or expired client secret, invalid or expired
JWT authentication, invalid or expired client X.509
certificate, or an unexpected client authentication
method",
"client_auth_id" : "cgXB4EyYViWPt6g2"
}
403 Forbidden
The request was denied due to the client registration or authorisation token not having the required scope.
Example:
HTTP/1.1 403 Forbidden
{
"error" : "access_denied",
"error_description" : "Client not registered for https://c2id.com/token/introspect scope"
}
500 Internal Server Error
An internal server error has occurred. Check the Connect2id server logs for details.
Example:
HTTP/1.1 500 Internal Server Error