Accessing data using JWT Token Exchange

Data sources protected by Feide are normally configured in the customer portal. The customer portal is used to configure policies for access to data sources and access levels. The data are accessed using JSON Web Tokens (JWTs). The data consumer obtains an OpenID Connect (OIDC) access token. It exchanges it for another token tailored for the data source, carrying all information the source needs to determine what information the consumer may access. This token is a JWT. It is short lived and digitally signed, allowing the data source to verify that it was issued by Feide, intended for the source, and still valid. The exchange conforms to RFC 8693 - Oauth2 token exchange.

In order to access a data source, you need a Feide service registered in the customer portal. It may be a service that users log in to, or a headless service with no associated user. It needs an OpenID Connect configuration with rights to access the data source and the appropriate access levels within it.

The data owner must approve access to the data, unless they have chosen to make the data source public.

Access starts with an OIDC access token. This could be the token the service receives when the user logs in, or a token which a headless service obtains with the client credentials flow.

Next, the service presents the access token to Feide and, if successful, receives back a JWT token for the data source. The request to Feide is a token exchange request to the token endpoint. For this request, grant type urn:ietf:params:oauth:grant-type:token-exchange is used. The response from the token endpoint is a token exchange response, which, unless the request fails, includes a JWT access token.

With each request to a data source endpoint, the service includes the JWT as a bearer token in the Authorization header. The data source verifies the signature of the token and checks that it is still valid, issued by Feide and intended for the data source. Finally, it checks which access levels the token authorizes, and responds appropriately.

Token exchange request

A token exchange request includes audience and scope parameters. The audience must be the data source UUID registered in the customer portal, prefixed by Example: The valid values for scopes are the identifiers of the access levels which are registered in the customer portal for the data source.

A token exchange request is made to the token endpoint using the HTTP “POST” method. Parameters are included in the HTTP request entity-body using the application/x-www-form-urlencoded format. The parameters are:


The UUID of the data source the JWT is intended for, prefixed by


The ID of the application making the exchange request.


The client secret of the application.


The value urn:ietf:params:oauth:grant-type:token-exchange selects Oauth2 token exchange.


A space separated list of identifiers of desired access levels. It is up to the data source how to interpret them.


An access token obtained from Feide. It should give the application access to the access levels given as scope in the data source given as audience.


Must be urn:ietf:params:oauth:token-type:access_token.

Here is an example:

content-type: application/x-www-form-urlencoded

&scope=read append

Successful response

A successful response has status 200 and an application/json body with the following attributes:


The type is Bearer.


The type is urn:ietf:params:oauth:token-type:jwt.


The JWT that was issued.


Number of seconds until JWT expires.


The scopes that were granted.

Here is an example:

    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI...",
    "token_type": "Bearer",
    "issued_token_type": "urn:ietf:params:oauth:token-type:jwt",
    "expires_in": 299,
    "scope": "read append"

JWT access token

The token is an ASCII string. It is intended for a third party data source. It consists of a header, a payload and a signature, with a . between them. Each are base64url encoded. See RFC 7519 - JSON Web Token (JWT). The payload is a json object containing claims.

If the token authenticates a user, it may contain claims about the user. A claim is only included if the service that requested the token and the data source both are authorized to access the claim.

The following claims are always included in the token:


Audience. The data source should only accept the token if it is the intended audience.


Issuer. Value is if token was issued by Feide.


Time of issue. This and other time attributes are given in seconds since 1970-01-01T0:0:0 UTC.


Expiration time.


Not valid before time. Protects against clock skew.


ID of the application that requested the token.


Subject - the identity which the token authenticates. Can be a dataporten user ID or a client ID.


The scopes that were granted.


Actor. It represents a chain of delegation. E.g., an application could authorize a data source to access another on its behalf. We do not currently support delegation in JWT tokens, so the chain is only one level deep. It is a json object with a single attribute: sub, with the same value as client_id in the token.

The following user claims may be included:


Name of user who the token authenticates.


Picture of user.

Secondary user ID of user.

eduPersonPrincipalName of user. Only for users who authenticated to the Feide IDP.

Norwegian national identity number of user. Only for users who authenticated to ID-porten.

Here is an example of what the payload may look like after decoding:

    "aud": "",
    "iss": "",
    "exp": 1610448035,
    "iat": 1610447735,
    "nbf": 1610447735,
    "client_id": "208335d4-e8c1-4910-8928-05b2e5b14127",
    "sub": "208335d4-e8c1-4910-8928-05b2e5b14127",
    "scope": "read append",
    "act": {
        "sub": "208335d4-e8c1-4910-8928-05b2e5b14127",

Validating a JWT access token

The consumer must validate the access token. In particular, iss has to be and aud has to be the same as in the request. See the JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens for full details about JWT access token validation. Furthermore, the token is only valid if the current time is in the interval between the iat and exp timestamps.

Token lifetimes

A JWT cannot be reliably revoked. Therefore, the lifetime is only 5 minutes. If the application needs access after the token has expired, it must obtain a new one.