This page applies to Apigee and Apigee hybrid.
  
    View 
    Apigee Edge documentation.
  
  
       
 
  
This topic explains how to generate, verify, and refresh JWT access tokens using the OAuthV2 policy.
Introduction
The JWT operations allow the OAuthV2 policy to generate, verify, and refresh access tokens that conform to IETF RFC 9068, a standard that describes how to issue access tokens in JWT format. JWTs are commonly used to share claims or assertions between connected applications. Issuing OAuthV2 access tokens in JWT format is an alternative to issuing opaque access tokens.
When configured for JWT, the OAuthV2 policy generates and returns a Base64-encoded JWT that consists of a header, a payload, and a signature separated by dots. For example:
 
  
  The encoded contents of these elements
  depend on how you configure the OAuthV2 policy. In the policy, you specify such parameters as
  the signing algorithm and payload elements like subject and name. For example, the header
  might decode as {"alg":"HS256","typ":"at+JWT"}, and the
  payload might decode as: {"sub":"ABC1234567","iat":1516239022}.
Header
  The header specifies a typ claim (always "at+JWT) and the alg claim, indicating the algorithm used to sign the JWT. Apigee
  supports RSA and HMAC algorithms: RS(256,384,512) and HS(256,384,512).
Payload
The payload consists of claims about the entity. Some claims must be provided in the policy configuration, while others are automatically generated by the Apigee runtime. The policy supports the following claims:
| Claim | Description | Provided by | 
|---|---|---|
| iss | The token issuer. This value is set as follows: (http|https)://{domain-name-for-proxy}/{proxy-basePath}. For
        example:https://api.mycompany.com/auth/v2. | Apigee | 
| sub | Either the Client ID or the ID of the resource owner (in the case of
  password or authorization grant types). If the appEndUserIdparameter is
          provided in the request, that value is used as the resource owner ID. You can
          control where this value is set using the<AppEndUser>element
          of the OAuthV2 policy. | API developer | 
| jti | A unique ID, represented as a UUID-backed random string to uniquely identify the token. | Apigee | 
| exp | The expiry time, in other words the time after which the token must be considered invalid. The value is expressed in epoch time (in seconds). | Apigee | 
| iat | The issued-at time, the time the token was created. The value is expressed in epoch time (in seconds). | Apigee | 
| client_id | The unique identifier of the client application. | API developer | 
| scope | The OAuth scope assigned to the token. See also Working with OAuth scopes. | API developer | 
Signature
The signature is generated using the encoded header, payload, secret/private key, and the algorithm. The signature is used to ensure that the contents of the token have not been tampered with.
For more information about JWT-format OAuth 2.0 access tokens, see the IETF RFC 9068: JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens.
Prerequisites
This document assumes that you understand how to generate and verify OAuthV2 access tokens using the OAuthV2 policy. Whether you use the JWT operations or the traditional operations that create opaque string tokens, the basic use of the OAuthV2 policy is the same. You can use JWT access tokens with all of the supported OAuthV2 grant types. See also Introduction to OAuth 2.0.
Generating
  Use the GenerateJWTAccessToken and GenerateJWTAccessTokenImplicitGrant
  operations to generate a JWT access token with the
  OAuthV2 policy. These operations are similar to the policy's traditional GenerateAccessToken and GenerateAccessTokenImplicitGrant
  operations. The main difference is that the JWT operation returns a JWT-formatted access token
  instead
  of an opaque string token. See also Get OAuth 2.0 tokens.
  The following examples show how to use these operations
  in the OAuthV2 policy. The examples use the client_credentials grant type; however, you can
  use any of the supported grant types with these operations.
Generating a JWT-format token signed with an HMAC algorithm
  Specify the <Algorithm> element with one of the 
  HMAC (HS256/HS384/HS512) algorithms. Also provide the <SecretKey>.
  The following example shows a policy configured to generate a JWT signed with the HS512
  algorithm, using the specified secret key.
<OAuthV2 name="generate-policy">
  <Operation>GenerateJWTAccessToken</Operation>
  <SupportedGrantTypes>
    <GrantType>client_credentials</GrantType>
  </SupportedGrantTypes>
  <GenerateResponse enabled="true"/>
  <Algorithm>HS512</Algorithm>
  <SecretKey>
    <Value ref="private.mysecretkey"/>
  </SecretKey>
  <ExpiresIn ref="kvm.oauth.expires_in">3600000</ExpiresIn>
</OAuthV2>Generating a JWT-format token signed with an RSA algorithm
  Specify one of the RSA algorithms (one of RS256/RS384/RS512) in the <Algorithm> element, and provide 
  the private key in the <PrivateKey> element. The following example shows a policy 
  configured to generate a JWT signed with an RSA private key using the RS256 algorithm.
<OAuthV2 name="generate-policy">
  <Operation>GenerateJWTAccessToken</Operation>
  <SupportedGrantTypes>
    <GrantType>client_credentials</GrantType>
  </SupportedGrantTypes>
  <GenerateResponse enabled="true"/>
  <Algorithm>RS256</Algorithm>
  <PrivateKey>
    <Value ref="private.rsa-privatekey-1"/>
  </PrivateKey>
  <ExpiresIn ref="kvm.oauth.expires_in">3600000</ExpiresIn>
</OAuthV2>Generating a JWT-format token with the implicit grant type
  The GenerateJWTAccessTokenImplicitGrant operation generates a JWT access token
  using the implicit grant type. It automatically gives the token the implicit grant type;
  therefore, the <SupportedGrantTypes> element is not required. 
  Because it is a JWT, the <Algorithm> element is required. The following 
  example shows the use of the RS256 algorithm. Because of that, the <PrivateKey>
  element is required. See also
  Use the implicit grant type.
<OAuthV2 name="generate-policy">
  <Operation>GenerateJWTAccessTokenImplicitGrant</Operation>
  <GenerateResponse enabled="true"/>
  <Algorithm>RS256</Algorithm>
  <PrivateKey>
    <Value ref="private.rsa-privatekey-1"/>
  </PrivateKey>
  <ExpiresIn ref="kvm.oauth.expires_in">3600000</ExpiresIn>
</OAuthV2>Verifying
  Use the VerifyJWTAccessToken operation to verify a JWT access token with the
  OAuthV2 policy. This operation is similar to the VerifyAccessToken
  operation; the difference is that VerifyJWTAccessToken applies to tokens in JWT format, 
  while VerifyAccessToken applies to opaque tokens.
Verifying a JWT access token signed with an HMAC algorithm
  The following example shows how to configure the OAuthV2 policy to verify a JWT
  token that was signed with the HS512 algorithm. When using the VerifyJWTAccessToken operation
  with an HMAC algorithm, the policy configuration must use the <SecretKey> element
  to specify the secret key that was used to sign the JWT.
<OAuthV2 name="OAuthV2-verify-jwt">
  <Operation>VerifyJWTAccessToken</Operation>
  <Algorithm>HS512</Algorithm>
  <SecretKey>
    <Value ref="private.mysecretkey"/>
  </SecretKey>
</OAuthV2>Verifying a JWT access token signed with an RSA algorithm
  The following example shows how to configure the OAuthV2 policy to verify a JWT
  token that was signed with the RS512 algorithm. When using the VerifyJWTAccessToken operation
  with an RSA algorithm, the policy configuration must use the <PublicKey> element
  to specify the public key that corresponds to the private key that was used to sign the JWT.
<OAuthV2 name="OAuthV2-verify-jwt">
  <Operation>VerifyJWTAccessToken</Operation>
  <Algorithm>RS512</Algorithm>
  <PublicKey>
    <Value ref="propertyset.non-secrets.rsa-publickey-1"/>
  </PublicKey>
</OAuthV2>Refreshing
  Use the RefreshJWTAccessToken operation to refresh a JWT access token.
  This operation is similar to the policy's traditional RefreshAccessToken
  operation. See also Refreshing an access token.
Refreshing an HMAC-signed access token
  The following policy sample illustrates how to configure the OAuthV2 policy to refresh a JWT
  token that was signed with an HMAC algorithm. The <SecretKey>
  and <Algorithm> elements are required in this case.
The response of the refresh operation is similar to the response of a newly generated token. The refresh operation generates a new JWT token with an updated expiry time, keeping other claims the same.
<OAuthV2 name="RefreshAccessToken">
    <Operation>RefreshJWTAccessToken</Operation>
    <GenerateResponse enabled="true"/>
    <Algorithm>HS512</Algorithm>
    <SecretKey>
      <Value ref="private.mysecretkey"/>
    </SecretKey>
    <RefreshTokenExpiresIn ref="kvm.oauth.expires_in">3600000</RefreshTokenExpiresIn>
</OAuthV2>Refreshing an RSA-signed JWT access token
The following policy sample illustrates how to configure the OAuthV2 policy to refresh a JWT token that was signed with an RSA algorithm. See also Refreshing an access token.
<OAuthV2 name="RefreshAccessToken">
    <Operation>RefreshJWTAccessToken</Operation>
    <GenerateResponse enabled="true"/>
    <Algorithm>RS256</Algorithm>
    <PrivateKey>
      <Value ref="private.rsa-privatekey-1"/>
    </PrivateKey>
    <RefreshTokenExpiresIn ref="kvm.oauth.expires_in">3600000</RefreshTokenExpiresIn>
</OAuthV2>Sample token response
  For both generate and refresh operations, the response body looks similar to the following
  example. Note that the access_token is represented as a serialized JWT, and
  the refresh token is a traditional opaque token.
{ "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6ImF0K0pXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", "token_type": "Bearer", "developer.email": "developer@example.org", "token_type": "Bearer", "issued_at": "1658352381404", "expires_in": 1799, "refresh_token": "rVSmm3QaNa0xBVFbUISz1NZI15akvgLJ", "refresh_token_issued_at": "1658352381404", "refresh_token_expires_in": 86399, "refresh_token_status": "Approved", "refresh_count": "0", "organization_name": "cerruti", "api_product_list_json": [ "TestingProduct" ] }
Summary of required policy elements
The following table describes JWT-specific elements used in the preceding examples:
| Element | Type | Notes | 
|---|---|---|
| Algorithm | Static value | Specifies the algorithm used to sign the token. | 
| SecretKey | Referenced value | Provides the secret key used to verify or sign tokens with an HMAC algorithm: HS (256/384/512). | 
| PrivateKey | Referenced value | Provides the private key used to generate the token. Use only when the algorithm is an RSA algorithm: RS (256/384/512). | 
| PublicKey | Referenced value | Provides the public key used to verify the token. Use only when the algorithm is an RSA algorithm: RS (256/384/512). | 
Unsupported policy elements
The following OAuthV2 policy elements are not supported with JWT token configurations:
| Element | Notes | 
|---|---|
| ExternalAuthorization | When generating a JWT access token, the OAuthV2 policy will validate the client ID and Secret. | 
| ExternalAccessToken | When generating a JWT access token, the token will be signed by Apigee and
    the claims will be provided by Apigee either by default or through policy configuration.
    The policy does support ExternalRefreshToken, which can aid in
    migration use cases. | 
| RFCCompliantRequestResponse | The generation and refresh of JWT access tokens is RFC compliant by default. | 
Usage notes
- Encrypted JWTs are not supported.
- In addition to a JWT access token, the policy response also includes an opaque refresh token for grant types where refresh tokens are supported. Only the password and auth code grant types support refresh tokens.
- Include the Authorization header in requests sent to the proxy containing the OAuthV2 policy.
- You cannot revoke a JWT access token. The generated JWT token will remain valid until it expires. You can revoke a refresh token that is associated to a JWT access token.
- Generation, verification, and refresh of access tokens must be handled by Apigee. Although
  an external application or gateway that has access to the public or secret key can decode
  the contents of the JWT, the external application does not have information about the API products
  that are identified by the client_idclaim, and therefore cannot play a role in API proxy authorization.