Netherlands - Generic Functions for data exchange Implementation Guide
0.2.0 - ci-build
Netherlands - Generic Functions for data exchange Implementation Guide, published by Stichting Nuts. This guide is not an authorized publication; it is the continuous build for version 0.2.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/nuts-foundation/nl-generic-functions-ig/ and changes regularly. See the Directory of published versions
The transaction Introspect Access Token allows a resource server (Custodian) to validate and obtain metadata about an access token issued by an authorization server (Verifier).
The introspection returns the active state of the token along with additional the identity claims associated with the token. This information can be used by the resource server down stream during the authorization decision.
The introspection transaction is added so the access token format can be opaque to the resource server. This allows the authorization server to use any token format, including self-contained tokens such as JWTs, without requiring the resource server to understand the token format.
In case the access token is a self-contained token such as a JWT, the resource server can validate the token locally without needing to call the introspection endpoint. However, the resource server needs to be able to validate the token signature and parse the token claims which adds complexity and duplicates logic that is already present in the authorization server.
| Actor | Role |
|---|---|
| Custodian | Validates the access token and retrieves metadata about the token from the authorization server |
| Verifier | Provides an introspection endpoint to validate access tokens and return associated metadata |
The resource server initiates an introspect access token request using a HTTP POST request to the authorization server's introspection endpoint. The request includes the access token to be introspected.
Below is a non-normative example of an Introspect Access Token Request:
POST /introspect HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
token=Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU
The authorization server responds with a HTTP 200 OK response containing a JSON object in the body of the response. The JSON object includes an active boolean field indicating whether the token is valid.
The iss must be the decentralized identifier (DID) of the authorization server.
The aud must be the decentralized identifier (DID) of the custodian.
For a DPoP bound access token, the response also includes a cnf claim containing the public key information that can be used to verify the DPoP proof presented by the client as defined in Section 6.2 of RFC 9449.
The response may also include the identity claims associated with the token in the assertions a client_assertions properties. Claims are grouped by subject and each claim has an array of objects with the metadata of the claim, such as the issuer, validity period and the actual claim value.
Below is a non-normative example of an Introspect Access Token Response:
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"active": true,
"scope": "read write",
"token_type": "DPoP",
"exp": 1419356238,
"iat": 1419350238,
"nbf": 1419350238,
"aud": "did:web:custodian.example.com",
"iss": "did:web:verifier.example.com",
"jti": "123e4567-e89b-12d3-a456-426614174000",
"cnf": {
"jkt": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I"
},
"assertions": {
"did:web:example.com:users:john": {
"name": [{
"value": "John Doe",
"iss": "https://issuer.example.com",
"iat": 1618884473,
"exp": 1672531199
}],
"email": [{
"value": "john@example.com",
"iss": "https://issuer.example.com",
"iat": 1618884473,
"exp": 1672531199
},{
"value": "john.doe@other.example.com",
"iss": "https://other-issuer.example.com",
"iat": 1618884473,
"exp": 1672531199
}]
},
"did:web:org.example.com": {
"identifier": [{
"value": {
"type": "Organization",
"name": "Example Org",
"registrationNumber": "123456789"
},
"iss": "https://issuer.example.com",
"iat": 1618884473,
"exp": 1672531199
}]
}
},
"client_assertions": {
"did:web:example.com:apps:myapp": {
"app_id": [{
"value": "myapp",
"iss": "https://auth.example.com",
"iat": 1618884473,
"exp": 1672531199
}],
"certification": [{
"value": "UseCase1,UseCase2",
"iss": "https://auth.example.com",
"iat": 1618884473,
"exp": 1672531199
}]
}
}
}
Case 1: The access token is valid.
HTTP 200 (OK) is returned as the HTTP status code.
The response body contains a JSON object with the active field set to true and additional metadata about the token and identity claims.
Case 2: The access token is invalid or expired.
HTTP 200 (OK) is returned as the HTTP status code.
The response body contains a JSON object with the active field set to false. Other
fields may be omitted or set to null.
Case 3: The introspection request is malformed or missing required parameters.
HTTP 400 (Bad Request) is returned as the HTTP status code.
The response body contains an error message indicating the issue with the request.
The authorization server does not check the validity of the DPoP proof. The resource server must validate the DPoP proof separately by checking the cnf.jkt claim in the introspection response against the DPoP proof presented by the client. This claim contains the JWK thumbprint of the public key used to sign the DPoP proof. The resource server must ensure that the jkt value matches the thumbprint of the public key in the DPoP proof to confirm that the client possesses the private key corresponding to the public key.