JWT authentication plug-in

更新时间:
复制 MD 格式

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 a JWT in any way. API Gateway is responsible only for authenticating the JWT using a public key JWK.

  • Supports JWKs that do not contain a kid.

  • Supports the configuration of multiple JWKs.

  • Supports reading tokens directly from the header or query. 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 JWT is transmitted as Authorization bearer {token}, you can configure parameter: Authorization and parameterLocation: header to correctly read the token.

  • By adding the preventJtiReplay: true configuration, you can enable anti-replay checks based on claim:jti.

  • By adding the bypassEmptyToken: true configuration, you can skip verification and forward the request directly to the backend if the token does not exist.

  • By adding the ignoreExpirationCheck: true configuration, you can ignore the token's exp expiration 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 the public key. Keep your private key secure. The JWT authentication plug-in supports the following algorithms:

Signature algorithm

Supported alg values

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

Important

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-in reads the JWT value based on the configured parameter and parameterLocation. For example, parameter: X-Token and parameterLocation: header indicate that the JWT is read from the X-Token header of the request.

  • If a parameter with the same name as the parameter is configured on the API, you can omit parameterLocation. 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 configure parameter: Authorization and parameterLocation: header. The JWT plug-in can then correctly read the token value.

  • When preventJtiReplay: true is configured, the plug-in uses the jti field in the claims to perform an anti-replay check.

  • When bypassEmptyToken: true is configured, if the token parameter is empty, the check is skipped and the request is forwarded directly to the backend.

  • When ignoreExpirationCheck: true is configured, the exp expiration check is skipped. Otherwise, the gateway checks whether the token has expired.

  • If you need API Gateway to forward the claims in the token to the backend application, you can configure the forwarding parameters using the tokenParameters field.

    • 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, and formData.

      • 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 when parameter mapping is used and the request body is in form format.

  • You can configure a single key in the jwk field, or configure multiple keys in the jwks field.

    • Only one key without a kid field is allowed.

    • You can configure multiple keys that contain a kid, but each kid must be unique.

3. Verification rules

  • The plugin uses the configured parameter and parameterToken to obtain a token. If you want to forward requests to the backend when a token is not available, you need to configure bypassEmptyToken: true.

  • When you configure multiple keys, the selection follows these rules:

    • The key with a kid that matches the one in the request token is prioritized for signature verification.

    • Only one key without a kid can be configured. If no key with a matching kid is found, the key without a kid is used for signature verification.

    • If no key without a kid is configured, and the request token does not contain a kid or no key is matched using the kid, an A403JK error is reported.

  • If the token contains the iat, nbf, or exp fields, the JWT plug-in verifies the validity of these time fields. The unit of time is seconds (s).

  • By default, API Gateway verifies the exp expiration time field of the token. If you want to skip the exp expiration check, configure ignoreExpirationCheck: true.

  • If the tokenParameters field is configured for forwarding, a claim field is forwarded to the backend if it is present in the token's claims. A claim that 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

  1. Log on to the API Gateway console. In the navigation pane on the left, click API Management > Plug-in Management.

  2. On the Plug-ins page, click the Plug-in Datasets tab.

  3. 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.

  4. 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.

    Important

    When 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.
Note

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=073957d8d2823be4f6c0cad23c764558

5.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 jti is required when preventJtiReplay:true

When the anti-replay feature is configured in the JWT authorization plugin, the request does not provide a valid jti.

403

S403JU

Claim jti in JWT is used

When the anti-replay feature is configured in the JWT authorization plugin, the jti in the request has already been used.

403

A403JT

Invalid JWT: ${Reason}

The JWT provided in the request is invalid.

400

I400JD

JWT Deserialize Failed: ${Token}

The JWT provided in the request could not be parsed.

403

A403JK

No matching JWK, kid:${kid} not found

No matching JWK was found for the kid in the request JWT.

403

A403JE

JWT is expired at ${Date}

The JWT provided in the request has expired.

400

I400JP

Invalid JWT plugin config: ${JWT}

The JWT authentication plug-in is configured incorrectly.

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 claimName and parameterName values can be up to 32 characters long and can contain only letters, digits, hyphens (-), and underscores (_).

  • The alg for JWKs supports the following algorithms: RS256, RS384, RS512, ES256, ES384, ES512, HS256, HS384, and HS512.