All Products
Search
Document Center

API Gateway:jwt-logout

Last Updated:May 22, 2025

The jwt-logout plug-in uses Redis to implement weak state management for JSON Web Tokens (JWTs). The plug-in resolves the issue that JWTs do not support proactive logoff. You can also use the plug-in to implement single-device logon of an account. For example, an account is automatically logged off from a device when the account is used to log on to another device.

Plug-in type

Plug-in for authentication and authorization.

Fields

Field

Data type

Required

Default value

Description

jwks

string

No

-

The JSON string that is used to verify a JWT. When you use this plug-in together with the jwt-auth plug-in, you do not need to configure this field. For more information, see JSON Web Key (JWK).

clock_skew

number

No

60

The clock offset that is allowed when the exp and iat fields in a JWT are checked. Unit: seconds.

token_header

string

No

Authorization

The request header from which you can extract a JWT.

token_prefix

string

No

"Bearer"

The prefix of the value in the request header. After the prefix is removed, the remaining part of the request header is used as the JWT content.

redis

Redis

Yes

-

The Redis service configuration.

logout

Logout

No

-

The configuration that is used to implement the JWT logoff feature. If this field is not configured, the JWT logoff feature is disabled.

login

Login

No

-

The configuration that is used to implement the JWT single-device logon feature. If this field is not configured, the JWT single-device logon feature is disabled.

The following table describes the configuration fields of the Redis type.

Field

Data type

Required

Default value

Description

service

string

Yes

-

The name of the Redis service. Examples:

  • Fixed address: my-redis.static

  • DNS domain name: my-redis.dns

  • ACK: my-redis.default.svc.cluster.local

port

number

Yes

-

The port number of the Redis service.

username

string

No

-

The username that is used in the Redis AUTH command.

password

string

No

-

The password that is used in the Redis AUTH command.

timeout

number

No

1000

The timeout period of a Redis command. Unit: millisecond.

The following table describes the configuration fields of the Logout type.

Field

Data type

Required

Default value

Description

key_prefix

string

No

higress_jwt_logout_

The prefix of the key stored in Redis.

key

array of string

No

["jti"]

The key in the JWT payload to identify a JWT. If the same key is contained in the payloads of multiple JWTs, the JWTs are considered the same one. If the key is not contained in the JWT payload, the error 401 invalid token is reported.

path

string

No

/jwt_logout

The character string that is used to match the URL path suffix. If the URL path suffix matches the specified string, the account that uses the JWT in the current request is logged off. The JWT cannot be used any more.

error_status

number

No

401

The error code that is returned upon logoff.

error_body

string

No

'{"message":"invalid token"}'

The body of the response upon logoff.

ttl

number

No

-

The time to live (TTL) of the key stored in Redis. Unit: seconds. This configuration determines the duration in which the JWT is invalidated after logoff. If this configuration is not specified, the TTL is equal to the value of the exp field in the payload minus the current time. If the payload does not contain the exp field, the default TTL is 86,400 seconds (24 hours).

The following table describes the configuration fields of the Login type.

Field

Data type

Required

Default value

Description

key_prefix

string

No

higress_jwt_logout_

The prefix of the key stored in Redis.

key

array of string

No

["iss","aud","sub"]

The single-device logon identifier in the JWT payload. If the JWT payload in the current request contain the same field but the request JWT is not exactly the same as the JWT of a successful logon, the system considers the current request as a repeated logon request and rejects the request. The system allows the request until the key of the JWT for the successful logon in Redis expires. If the JWT payload in the current request does not contain the field, the error 401 invalid token is reported.

path

string

No

/jwt_login

The character string that is used to match the URL path suffix. If the URL path suffix matches the specified string, the account is forced to log on to the system by using the JWT in the current request. The JWT that is used for a successful logon and has the same payload characteristics is invalidated upon logoff.

error_status

number

No

403

The error code that is returned for repeated logons.

error_body

string

No

'{"message":"already login on other device"}'

The response body for repeated logons.

ttl

number

No

-

The TTL of the key stored in Redis. Unit: seconds. The field determines the validity period of a JWT that is used for single-device logon. If this field is not specified, the TTL is equal to the value of the exp field in the payload minus the current time. If the payload does not contain the exp field, the default TTL is 86,400 seconds (24 hours).

Configuration examples

Use an ApsaraDB for Redis instance

  1. Create an ApsaraDB for Redis instance. For more information, see Overview.

  2. Enable the logoff and logon configurations. When the plug-in processes a request, one Redis read request for logoff configuration checking and two Redis read requests for logon configuration checking are generated. In rare cases such as a logoff or first-time logon, two additional Redis write requests are generated. To estimate the capacity of the ApsaraDB for Redis instance, you can multiply the throughput of requests processed by the plug-in by 2.

  3. After you configure the ApsaraDB for Redis instance, obtain the VPC endpoint of the instance. Example: r-xxxxxxx.redis.rds.aliyuncs.com.

  4. Add a service. Select DNS Domain Name from the Service Source drop-down list, enter the Redis port number (6379 in most cases) in the Service Port field, enter the VPC endpoint in the Domain Names field, and select Disabled from the TLS Mode drop-down list. For more information, see Create a service.

  5. Add the following content to the plug-in configuration to connect to the ApsaraDB for Redis instance:

    redis:
      service: redis.dns
      port: 6379

    If you configure a password for the Redis service, add the following content:

    redis:
      service: redis.dns
      port: 6379
      password: ****** # Enter the password that you specify.

Implement the JWT logoff feature

Use scenarios

JWTs are stateless tokens. If a JWT is issued, it is valid until it expires. You can use the jwt-logout plug-in to implement forced logoffs when a specific JWT is used.

How it works

  • If the suffix of the request path matches the path in the plug-in configuration, the logoff mechanism is triggered. The ApsaraDB for Redis instance records the JWT for the logoff. The key stored in the ApsaraDB for Redis instance consists of the configured prefix and the key and value extracted from the current JWT payload.

  • If the payload of the JWT carried in the request matches the characteristics of the key stored in the ApsaraDB for Redis instance, the system considers the current JWT invalid and rejects the request.

  • The default expiration time of the key stored in the ApsaraDB for Redis instance is calculated based on the exp field in the JWT payload. This means that the key can be stored until the JWT expires.

Note
  • The default recommended logoff key of the plug-in is ["jti"], in which jti is the payload field that uniquely identifies a JWT. As specified in JWT standards, if the jti value in the JWT payload is the same as that recorded in the ApsaraDB for Redis instance, the entire JWT is exactly the same. Therefore, jti can be used to mark the logoff status of a JWT.

  • The concatenation rule of the key stored in the ApsaraDB for Redis instance: <key_prefix><PayloadKey>##<PayloadValue>. PayloadKey is a list of keys that are delimited by number signs (#). PayloadValue is a list of key values that are delimited by number signs (#). Example: higress_jwt_logout_jti#iss##xxxxx#abcde.

  • This plug-in can only invalidate the token that is carried in the current request during the logoff. You can also manually specify the token in the ApsaraDB for Redis console based on the preceding key concatenation rule. If the gateway finds that the key exists in the ApsaraDB for Redis instance, the gateway rejects the access request that is based on the relevant JWT.

Example

Plug-in configuration:

redis:
  service: redis.dns
  port: 6379
jwks: |
  {
    "keys": [
      {
        "kty": "oct",
        "kid": "123",
        "k": "hM0k3AbXBPpKOGg__Ql2Obcq7s60myWDpbHXzgKUQdYo7YCRp0gUqkCnbGSvZ2rGEl4YFkKqIqW7mTHdj-bcqXpNr-NOznEyMpVPOIlqG_NWVC3dydBgcsIZIdD-MR2AQceEaxriPA_VmiUCwfwL2Bhs6_i7eolXoY11EapLQtutz0BV6ZxQQ4dYUmct--7PLNb4BWJyQeWu0QfbIthnvhYllyl2dgeLTEJT58wzFz5HeNMNz8ohY5K0XaKAe5cepryqoXLhA-V-O1OjSG8lCNdKS09OY6O0fkyweKEtuDfien5tHHSsHXoAxYEHPFcSRL4bFPLZ0orTt1_4zpyfew",
        "alg": "HS256"
      }
    ]
  }
logout:
  path: "/jwt_logout"
  key: ["jti"]
  error_status: 401
  error_body: |
    {"message":"invalid token"}
  1. Trigger a logoff.

    curl  http://xxx.hello.com/test/jwt_logout -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJ4eHh4IiwiaXNzIjoiYWJjZCIsInN1YiI6InRlc3QiLCJhdWQiOiJ3d3cudGVzdC5jb20iLCJpYXQiOjE2NjU2NjA1MjcsImV4cCI6MTg2NTY3MzgxOX0.tmKF6qc1mOWNyCCzBOT2XKNoEGeEgr3EbhTKAQfq1io'
    
    # The following result is returned:
    {"message": "logout success"}

    Token payload:

    {
        "jti": "xxxx",
        "iss": "abcd",
        "sub": "test",
        "aud": "www.test.com",
        "iat": 1665660527,
        "exp": 1865673819
    }

    In this case, the key higress_jwt_logout_jti##xxxx is stored in the ApsaraDB for Redis instance.

  2. After the logoff, access based on the JWT is not allowed.

    curl  http://xxx.hello.com/test/abc -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJ4eHh4IiwiaXNzIjoiYWJjZCIsInN1YiI6InRlc3QiLCJhdWQiOiJ3d3cudGVzdC5jb20iLCJpYXQiOjE2NjU2NjA1MjcsImV4cCI6MTg2NTY3MzgxOX0.tmKF6qc1mOWNyCCzBOT2XKNoEGeEgr3EbhTKAQfq1io'
    
    # The following result is returned:
    {"message":"invalid token"}

Implement forced logoff based on JWTs

Use scenarios

When an account is used for logon to multiple devices and JWT authentication is used for logon, different JWTs may be issued on different devices. In this case, you can use the jwt-logout plug-in to allow the account to log on to only one device at a time.

How it works

  • When a request is initiated, the system extracts the JWT from the current request and constitutes a Redis key based on the configured prefix and the key and value extracted from the current JWT payload. Then, the system queries the value that corresponds to the key in the ApsaraDB for Redis instance. If the value is inconsistent with the key value of the current JWT, the system rejects the access request.

  • If the value does not exist, the current JWT is written to the Redis key. The default expiration time of the key in the ApsaraDB for Redis instance is calculated based on the exp field in the JWT payload. This means that the key can be stored until the JWT expires. During the validity period of the JWT, access requests based on other JWTs that have the same payload characteristics are not allowed.

  • If the request suffix matches the path in the plug-in configuration, the forced logoff mechanism is triggered and the current JWT is written to the value of the associated Redis key. The JWT that is used for a successful logon and has the same payload characteristics is invalidated upon logoff. This ensures single-device logon.

Note
  • The default recommended logon key of the plug-in is ["iss","aud","sub"]. In the key, iss indicates the JWT issuer, aud indicates the JWT use scenario, and sub indicates the subject of the JWT. In most cases, the combination can be used to ensure single-device logon.

  • The concatenation rule of the key stored in the ApsaraDB for Redis instance: <key_prefix><PayloadKey>##<PayloadValue>. PayloadKey is a list of keys that are delimited by number signs (#). PayloadValue is a list of key values that are delimited by number signs (#). Example: higress_jwt_login_iss#aud#sub##xxxxx#abcde#fffff.

  • For the JWTs that have the same payload characteristics, the first JWT used for requests is automatically written to the ApsaraDB for Redis instance. This helps implement the single-device logon feature of the plug-in. Therefore, you do not need to call the API operation for forced logon. You need to call the API operation only when forced logoff is required in logon scenarios.

  • When you trigger the logoff logic, the logon key of the current JWT stored in the ApsaraDB for Redis instance is cleared. This rule also applies when you enable the JWT logoff feature.

Example

Plug-in configuration:

redis:
  service: redis.dns
  port: 6379
jwks: |
  {
    "keys": [
      {
        "kty": "oct",
        "kid": "123",
        "k": "hM0k3AbXBPpKOGg__Ql2Obcq7s60myWDpbHXzgKUQdYo7YCRp0gUqkCnbGSvZ2rGEl4YFkKqIqW7mTHdj-bcqXpNr-NOznEyMpVPOIlqG_NWVC3dydBgcsIZIdD-MR2AQceEaxriPA_VmiUCwfwL2Bhs6_i7eolXoY11EapLQtutz0BV6ZxQQ4dYUmct--7PLNb4BWJyQeWu0QfbIthnvhYllyl2dgeLTEJT58wzFz5HeNMNz8ohY5K0XaKAe5cepryqoXLhA-V-O1OjSG8lCNdKS09OY6O0fkyweKEtuDfien5tHHSsHXoAxYEHPFcSRL4bFPLZ0orTt1_4zpyfew",
        "alg": "HS256"
      }
    ]
  }
login:
  path: "/jwt_login"
  key: ["iss","aud","sub"]
  error_status: 403
  error_body: |
    {"message":"already login on other device"}
  1. Perform a successful logon operation.

    curl  http://xxx.hello.com/test/abc -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJ6enp6IiwiaXNzIjoiYWJjZCIsImF1ZCI6Ind3dy5leGFtcGxlLmNvbSIsInN1YiI6InRlc3QiLCJpYXQiOjE2NjU2NjA1MjcsImV4cCI6MTg2NTY3MzgxOX0.WljMr5ucxfLF8SmeaaL25c0QG3IX04HoD0als9gglYg'

    Token payload:

    {
        "jti": "zzzz",
        "iss": "abcd",
        "aud": "www.example.com",
        "sub": "test",
        "iat": 1665660527,
        "exp": 1865673819
    }

    In this case, the key higress_jwt_login_iss#aud#sub##abcd#www.example.com#abcd is stored in the ApsaraDB for Redis instance and the value is the same as that in the current JWT.

  2. Reject an access request when the JWT payload in the request has the same payload characteristics.

    curl  http://xxx.hello.com/test/abc -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJqdGkiOiJ5eXl5eSIsImlzcyI6ImFiY2QiLCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJ0ZXN0IiwiaWF0IjoxNjY1NjYwNTI5LCJleHAiOjE4NjU2NzM4MTl9.6vi6eKPWSKHQxfzBPrj3-SWI4Q5zGtWhqp38JIN3FEo'
    
    # The following result is returned:
    {"message":"already login on other device"}

    Token payload:

    {
        "jti": "yyyyy",
        "iss": "abcd",
        "aud": "www.example.com",
        "sub": "test",
        "iat": 1665660527,
        "exp": 1865673819
    }

    The payload characteristics are the same for the current JWT and the JWT in Step 1. However, the non-characteristic field jti is different between the two JWTs. Therefore, the access request based on the JWT is rejected.

  3. Perform a forced logon.

    curl  http://xxx.hello.com/test/jwt_login -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJqdGkiOiJ5eXl5eSIsImlzcyI6ImFiY2QiLCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJ0ZXN0IiwiaWF0IjoxNjY1NjYwNTI5LCJleHAiOjE4NjU2NzM4MTl9.6vi6eKPWSKHQxfzBPrj3-SWI4Q5zGtWhqp38JIN3FEo'
    
    # The following result is returned:
    {"message":"login success"}

    In this case, the key higress_jwt_login_iss#aud#sub##abcd#www.example.com#abcd is stored in the ApsaraDB for Redis instance and the value is replaced by the value in the current JWT.

    Use the current JWT to successfully access the page.

    curl  http://xxx.hello.com/test/abc -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJqdGkiOiJ5eXl5eSIsImlzcyI6ImFiY2QiLCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJ0ZXN0IiwiaWF0IjoxNjY1NjYwNTI5LCJleHAiOjE4NjU2NzM4MTl9.6vi6eKPWSKHQxfzBPrj3-SWI4Q5zGtWhqp38JIN3FEo'

    If you use the JWT in Step 1, a failure message is returned.

    curl  http://xxx.hello.com/test/abc -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJqdGkiOiJ4eHh4IiwiaXNzIjoiYWJjZCIsImF1ZCI6Ind3dy5leGFtcGxlLmNvbSIsInN1YiI6InRlc3QiLCJpYXQiOjE2NjU2NjA1MjcsImV4cCI6MTg2NTY3MzgxOX0.P0WtBTHJzUJvklu9q8XSRszfPbgojrZHg7t4ZaYfKGo'
    
    # The following result is returned:
    {"message":"already login on other device"}

Error codes

HTTP status code

Error message

Reason

401

invalid token

No JWT is provided in the request header, the JWT format is invalid, or the JWT is expired.

500

redis server error

Access to the ApsaraDB for Redis instance times out or fails.