JSON Web Token (JWT), as defined in RFC7519, provides a convenient authentication solution for gateways to authenticate requests. API Gateway can host a user's public JWK to perform JWT authentication on requests and forward the claims to the backend as parameters. This simplifies backend application development. This topic describes how to configure the JWT authentication plug-in. For more information about the JWT token authentication process and basic concepts, see JWT-based token authentication.
The OpenId Connect feature, which was previously configured on APIs, is now implemented by the JWT authentication plug-in. We recommend that you use the JWT authentication plug-in. The JWT authentication plug-in provides the following advantages over the OpenId Connect authentication that is configured on an API:
You do not need to configure an additional
authorization API. You can generate and distribute aJWTin any way. API Gateway is responsible only for authenticating theJWTusing apublic key JWK.Supports
JWKsthat do not contain akid.Supports the configuration of multiple
JWKs.Supports reading tokens directly from the
headerorquery. You do not need to set a token parameter for each API.Supports reading tokens from a field in the request's cookie header.
When a
JWTis transmitted asAuthorization bearer {token}, you can configureparameter: AuthorizationandparameterLocation: headerto correctly read the token.By adding the
preventJtiReplay: trueconfiguration, you can enable anti-replay checks based onclaim:jti.By adding the
bypassEmptyToken: trueconfiguration, you can skip verification and forward the request directly to the backend if the token does not exist.By adding the
ignoreExpirationCheck: trueconfiguration, you can ignore the token'sexpexpiration check.
If you configure a JWT authentication plug-in and bind it to an API for which the OpenID Connect feature is already configured, the plug-in's configuration overwrites the OpenID Connect configuration on the API.
1. Obtain a JWK (Json Web Key)
The JWT authentication plug-in uses JSON Web Keys (JWK), as defined in RFC7517, to sign and authenticate JWTs. To configure a JWT authentication plug-in, you must first generate a valid JSON Web Key. You can generate a key yourself or use an online JSON Web Key Generator tool, such as https://tools.top/jwt-encode.html. The following is an example of a valid JSON Web Key. The private key is used to sign the token, and the public key is configured in the JWT authentication plug-in to authenticate the token. A valid JWK has the following format:
{
"kty": "RSA",
"e": "AQAB",
"kid": "O9fpdhrViq2zaaaBEWZITz",
"use": "sig",
"alg": "RS256",
"n": "qSVxcknOm0uCq5vGsOmaorPDzHUubBmZZ4UXj-9do7w9X1uKFXAnqfto4TepSNuYU2bA_-tzSLAGBsR-BqvT6w9SjxakeiyQpVmexxnDw5WZwpWenUAcYrfSPEoNU-0hAQwFYgqZwJQMN8ptxkd0170PFauwACOx4Hfr-9FPGy8NCoIO4MfLXzJ3mJ7xqgIZp3NIOGXz-GIAbCf13ii7kSStpYqN3L_zzpvXUAos1FJ9IPXRV84tIZpFVh2lmRh0h8ImK-vI42dwlD_hOIzayL1Xno2R0T-d5AwTSdnep7g-Fwu8-sj4cCRWq3bd61Zs2QOJ8iustH0vSRMYdP5oYQ"
} This example shows the JSON format. If you use YAML to configure the plug-in, you must convert the key to the YAML format.
For a
JWT authentication plug-in, you only need to configure thepublic key. Keep yourprivate keysecure. The JWT authentication plug-in supports the following algorithms:
Signature algorithm | Supported |
RSASSA-PKCS1-V1_5 with SHA-2 | RS256, RS384, RS512 |
Elliptic Curve (ECDSA) with SHA-2 | ES256, ES384, ES512 |
HMAC using SHA-2 | HS256, HS384, HS512 |
When you configure a key of the HS256, HS384, or HS512 type, the key must be a Base64 URL-encoded value. If you encounter an "Invalid Signature" error, check whether your key format is consistent with the key that was used to generate the token.
2. Plug-in configuration
You can configure the plug-in in either JSON or YAML format. The two formats share the same schema. You can use a YAML to JSON converter tool to convert between the formats. The following code shows a template in the YAML format.
---
parameter: X-Token # The parameter from which the JWT is retrieved. This corresponds to an API parameter.
parameterLocation: header # The location from which the JWT is retrieved. Supported values: query and header. This parameter is optional if the API request mode is mapping. This parameter is required if the API request mode is pass-through.
preventJtiReplay: false # Specifies whether to enable the anti-replay check for jti. Default value: false.
bypassEmptyToken: false # Specifies whether to skip verification and forward the request to the backend when the token is empty.
ignoreExpirationCheck: false # Specifies whether to ignore the check for the exp expiration time.
orAppAuth: false # Default value: false. Both Alibaba Cloud APP authentication and the JWT plug-in are verified. If this is set to true, if one authentication method passes, the other is skipped.
claimParameters: # Claim parameter transformation. The gateway maps JWT claims to backend parameters.
- claimName: aud # The name of the claim. Public and private claims are supported.
parameterName: X-Aud # The name of the mapped parameter.
location: header # The location of the mapped parameter. Supported values: query, header, path, and formData.
- claimName: userId # The name of the claim. Public and private claims are supported.
parameterName: userId # The name of the mapped parameter.
location: query # The location of the mapped parameter. Supported values: query, header, path, and formData.
#
# The Public Key of the JSON Web Key.
jwk:
kty: RSA
e: AQAB
use: sig
alg: RS256
n: qSVxcknOm0uCq5vGsOmaorPDzHUubBmZZ4UXj-9do7w9X1uKFXAnqfto4TepSNuYU2bA_-tzSLAGBsR-BqvT6w9SjxakeiyQpVmexxnDw5WZwpWenUAcYrfSPEoNU-0hAQwFYgqZwJQMN8ptxkd0170PFauwACOx4Hfr-9FPGy8NCoIO4MfLXzJ3mJ7xqgIZp3NIOGXz-GIAbCf13ii7kSStpYqN3L_zzpvXUAos1FJ9IPXRV84tIZpFVh2lmRh0h8ImK-vI42dwlD_hOIzayL1Xno2R0T-d5AwTSdnep7g-Fwu8-sj4cCRWq3bd61Zs2QOJ8iustH0vSRMYdP5oYQ
#
# You can configure multiple JWKs. This can be configured together with the jwk field.
# When you configure multiple JWKs, kid is required. If the JWT does not provide a kid, verification fails.
jwks:
- kid: O9fpdhrViq2zaaaBEWZITz # When only one JWK is configured, kid is optional. However, if the JWT contains a kid, the gateway verifies the consistency of the kid.
kty: RSA
e: AQAB
use: sig
alg: RS256
n: qSVxcknOm0uCq5v....
- kid: 10fpdhrViq2zaaaBEWZITz # When only one JWK is configured, kid is optional. However, if the JWT contains a kid, the gateway verifies the consistency of the kid.
kty: RSA
e: AQAB
use: sig
alg: RS256
n: qSVxcknOm0uCq5v... The
JWT authentication plug-inreads the JWT value based on the configuredparameterandparameterLocation. For example,parameter: X-TokenandparameterLocation: headerindicate that the JWT is read from theX-Tokenheader of the request.If a parameter with the same name as the
parameteris configured on the API, you can omitparameterLocation. Otherwise, an error is reported during the call.If you use the Authorization header to transmit the token, such as
Authorization bearer {token}, you can configureparameter: AuthorizationandparameterLocation: header. The JWT plug-in can then correctly read the token value.When
preventJtiReplay: trueis configured, the plug-in uses thejtifield in theclaimsto perform an anti-replay check.When
bypassEmptyToken: trueis configured, if the token parameter is empty, the check is skipped and the request is forwarded directly to the backend.When
ignoreExpirationCheck: trueis configured, theexpexpiration check is skipped. Otherwise, the gateway checks whether the token has expired.If you need API Gateway to forward the
claimsin the token to the backend application, you can configure the forwarding parameters using thetokenParametersfield.claimName: The name of the claim in the token.parameterName: The name of the parameter forwarded to the backend.location: The location of the parameter forwarded to the backend. Supported values:header,query,path, andformData.If set to
path, the backend path must contain a parameter with the same name, such as/path/{userId}.If set to
formData, the claim can be correctly mapped to the backend form only whenparameter mappingis used and the request body is informformat.
You can configure a single key in the
jwkfield, or configure multiple keys in thejwksfield.Only one key without a
kidfield is allowed.You can configure multiple keys that contain a
kid, but eachkidmust be unique.
3. Verification rules
The plugin uses the configured
parameterandparameterTokento obtain a token. If you want to forward requests to the backend when a token is not available, you need to configurebypassEmptyToken: true.When you configure multiple keys, the selection follows these rules:
The key with a
kidthat matches the one in the request token is prioritized for signature verification.Only one key without a
kidcan be configured. If no key with a matchingkidis found, the key without akidis used for signature verification.If no key without a
kidis configured, and the request token does not contain akidor no key is matched using thekid, anA403JKerror is reported.
If the token contains the
iat,nbf, orexpfields, the JWT plug-in verifies the validity of these time fields. The unit of time is seconds (s).By default, API Gateway verifies the
expexpiration time field of the token. If you want to skip theexpexpiration check, configureignoreExpirationCheck: true.If the
tokenParametersfield is configured for forwarding, aclaimfield is forwarded to the backend if it is present in the token'sclaims. Aclaimthat is not present is not forwarded.
4. Using plug-in datasets with the JWT authentication plug-in
4.1 Create a JWT authentication plug-in dataset
Log on to the API Gateway console. In the navigation pane on the left, click .
On the Plug-ins page, click the Plug-in Datasets tab.
In the upper-right corner, click Create Dataset. In the dialog box that appears, enter a custom Name, set Type to JWT_JWK_LIST, and then click OK to create the dataset.
Go to the dataset that you created. In the upper-right corner, click Create Dataset Entry. In the Data Value field, configure the JWK that the JWT authentication plug-in supports. In the Expiration Time field, configure the validity period of the public key.
ImportantWhen you configure multiple JWKs, you must use a different kid for each JWK. The JWK data values must be configured in the order shown in the following example.
kty: RSA e: AQAB use: sig kid: N3h666 alg: RS256 n: qfzaxmlnl...
4.2 Example of configuring a plug-in dataset for the JWT authentication plug-in
---
parameter: X-Token # The parameter from which the JWT is retrieved. This corresponds to an API parameter.
parameterLocation: header # The location from which the JWT is retrieved. Supported values: query and header. This parameter is optional if the API request mode is mapping. This parameter is required if the API request mode is pass-through.
claimParameters: # Claim parameter transformation. The gateway maps JWT claims to backend parameters.
- claimName: aud # The name of the claim. Public and private claims are supported.
parameterName: X-Aud # The name of the mapped parameter.
location: header # The location of the mapped parameter. Supported values: query, header, path, and formData.
- claimName: userId # The name of the claim. Public and private claims are supported.
parameterName: userId # The name of the mapped parameter.
location: query # The location of the mapped parameter. Supported values: query, header, path, and formData.
preventJtiReplay: false # Specifies whether to enable the anti-replay check for jti. Default value: false.
ignoreExpirationCheck: true # Specifies whether to ignore the check for the exp expiration time.
jwkListDataSet: cb4f000b6b8244329ac25XXXc8a4f9d6 # The ID of the plug-in dataset.If the configuration does not take effect, submit a ticket to upgrade your instance.
5. Configuration examples
5.1. Configure a single JWK
---
parameter: X-Token # The parameter from which the JWT is retrieved. This corresponds to an API parameter.
parameterLocation: header # The location from which the JWT is retrieved. Supported values: query and header. This parameter is optional if the API request mode is mapping. This parameter is required if the API request mode is pass-through.
claimParameters: # Claim parameter transformation. The gateway maps JWT claims to backend parameters.
- claimName: aud # The name of the claim. Public and private claims are supported.
parameterName: X-Aud # The name of the mapped parameter.
location: header # The location of the mapped parameter. Supported values: query, header, path, and formData.
- claimName: userId # The name of the claim. Public and private claims are supported.
parameterName: userId # The name of the mapped parameter.
location: query # The location of the mapped parameter. Supported values: query, header, path, and formData.
preventJtiReplay: false # Specifies whether to enable the anti-replay check for jti. Default value: false.
#
# The Public Key of the JSON Web Key.
jwk:
kty: RSA
e: AQAB
use: sig
alg: RS256
n: qSVxcknOm0uCq5vGsOmaorPDzHUubBmZZ4UXj-9do7w9X1uKFXAnqfto4TepSNuYU2bA_-tzSLAGBsR-BqvT6w9SjxakeiyQpVmexxnDw5WZwpWenUAcYrfSPEoNU-0hAQwFYgqZwJQMN8ptxkd0170PFauwACOx4Hfr-9FPGy8NCoIO4MfLXzJ3mJ7xqgIZp3NIOGXz-GIAbCf13ii7kSStpYqN3L_zzpvXUAos1FJ9IPXRV84tIZpFVh2lmRh0h8ImK-vI42dwlD_hOIzayL1Xno2R0T-d5AwTSdnep7g-Fwu8-sj4cCRWq3bd61Zs2QOJ8iustH0vSRMYdP5oYQ
5.2. Configure multiple JWKs
---
parameter: Authorization # Get the token from the Authorization header.
parameterLocation: header # Get the token from the Authorization header.
claimParameters: # Claim parameter transformation. The gateway maps JWT claims to backend parameters.
- claimName: aud # The name of the claim. Public and private claims are supported.
parameterName: X-Aud # The name of the mapped parameter.
location: header # The location of the mapped parameter. Supported values: query, header, path, and formData.
- claimName: userId # The name of the claim. Public and private claims are supported.
parameterName: userId # The name of the mapped parameter.
location: query # The location of the mapped parameter. Supported values: query, header, path, and formData.
preventJtiReplay: true # Specifies whether to enable the anti-replay check for jti. Default value: false.
jwks:
- kid: O9fpdhrViq2zaaaBEWZITz # When you configure multiple JWKs, you must use different kids.
kty: RSA
e: AQAB
use: sig
alg: RS256
n: qSVxcknOm0uCq5v....
- kid: 10fpdhrViq2zaaaBEWZITz # When you configure multiple JWKs, you must use different kids.
kty: RSA
e: AQAB
use: sig
alg: RS256
n: qSVxcknOm0uCq5v...5.3. Read a token from a field in the request cookie
---
parameter: cookie # The parameter from which the JWT is retrieved. This corresponds to an API parameter.
parameterLocation: header # The location from which the JWT is retrieved. Supported values: query and header. This parameter is optional if the API request mode is mapping. This parameter is required if the API request mode is pass-through.
parameterSection: token # For example, the value of the cookie is username=tom ; token=abcsef
claimParameters: # Claim parameter transformation. The gateway maps JWT claims to backend parameters.
- claimName: aud # The name of the claim. Public and private claims are supported.
parameterName: X-Aud # The name of the mapped parameter.
location: header # The location of the mapped parameter. Supported values: query, header, path, and formData.
- claimName: userId # The name of the claim. Public and private claims are supported.
parameterName: userId # The name of the mapped parameter.
location: query # The location of the mapped parameter. Supported values: query, header, path, and formData.
preventJtiReplay: true # Specifies whether to enable the anti-replay check for jti. Default value: false.
jwks:
- kid: O9fpdhrViq2zaaaBEWZITz # When you configure multiple JWKs, you must use different kids.
kty: RSA
e: AQAB
use: sig
alg: RS256
n: qSVxcknOm0uCq5v....
- kid: 10fpdhrViq2zaaaBEWZITz # When you configure multiple JWKs, you must use different kids.
kty: RSA
e: AQAB
use: sig
alg: RS256
n: qSVxcknOm0uCq5v...In some web scenarios, for security reasons, you may want to save a token in a specified field within a cookie. The API Gateway JWT plug-in supports reading a token from a field in the request's cookie. You can use the parameterSection parameter to specify the field name. For example, if the request's cookie header is as follows, API Gateway can extract the token from the cookie.
Cookie: acw_tc=123; token=0QzRCMDBBQUYwRjE1MjYxQzU0QjY4NEM5MTc1NTQ1OUVCOTIzNzA4RDk3MDg5MzlDOTMQTVENDZCRUI1NkYyMEUyO; csrf=073957d8d2823be4f6c0cad23c7645585.4 Configure a blacklist
A blacklist in the JWT authentication plug-in is used to block requests from users who have obtained a valid token but have since been added to the blacklist. For this scenario, the API Gateway JWT authentication plug-in, combined with the plug-in dataset feature, can reject requests based on claim parameters decrypted from the token. API Gateway can not only reject requests that meet the blocking conditions but also customize the rejection response. The following code shows how to configure this. Note all parameter definitions that start with `block`:
---
parameter: Authorization # Get the token from the Authorization header.
parameterLocation: header # Get the token from the Authorization header.
claimParameters: # Claim parameter transformation. The gateway maps JWT claims to backend parameters.
- claimName: aud # The name of the claim. Public and private claims are supported.
parameterName: X-Aud # The name of the mapped parameter.
location: header # The location of the mapped parameter. Supported values: query, header, path, and formData.
- claimName: userId # The name of the claim. Public and private claims are supported.
parameterName: userId # The name of the mapped parameter.
location: query # The location of the mapped parameter. Supported values: query, header, path, and formData.
blockClaimParameterName: userId # This parameter is used as the condition for the blacklist logic. If the value of this parameter is in the blockByDataSet dataset, the request is blocked.
blockByDataSet: 87b65008e92541938537b1a4a236eda5 # The blacklist dataset.
blockStatusCode: 403 # The status code of the response for a rejected request.
blockResponseHeaders: # The header of the response for a rejected request.
Content-Type: application/xml
blockResponseBody: # The body of the response for a rejected request.
<Reason>be blocked</Reason>
jwks:
- kid: O9fpdhrViq2zaaaBEWZITz # When you configure multiple JWKs, you must use different kids.
kty: RSA
e: AQAB
use: sig
alg: RS256
n: qSVxcknOm0uCq5v....6. Related error codes
Status | Code | Message | Description |
400 | I400JR | JWT required | The JWT parameter was not found. |
403 | S403JI | Claim | When the anti-replay feature is configured in the |
403 | S403JU | Claim | When the anti-replay feature is configured in the |
403 | A403JT | Invalid JWT: ${Reason} | The |
400 | I400JD | JWT Deserialize Failed: | The |
403 | A403JK | No matching JWK, | No matching |
403 | A403JE | JWT is expired at | The |
400 | I400JP | Invalid JWT plugin config: ${JWT} | The |
If an unexpected response code is returned, check the X-Ca-Error-Code header for the ErrorCode and the X-Ca-Error-Message header for the ErrorMessage. If the A403JT or I400JD error code is returned, you can go to jwt.io to check the validity and format of your token.
7. Limits
The size of the plug-in metadata cannot exceed 50 KB.
You can forward a maximum of 16 parameters. The
claimNameandparameterNamevalues can be up to 32 characters long and can contain only letters, digits, hyphens (-), and underscores (_).The
algfor JWKs supports the following algorithms: RS256, RS384, RS512, ES256, ES384, ES512, HS256, HS384, and HS512.