Rejecting Revoked Tokens¶
Follow the below steps to enable Real-time and Persistent token revocation. This documentation explains the steps required to handle revoked JWTs. The same steps can be used for handling revoked opaque tokens. However, for opaque tokens, you only need to enable real-time notifications.
Enabling revoked token notifications¶
Let's use the following sample scenario.
- Both Real-time Notifications and Persistent Notifications are enabled.
- Default etcd based persistent notifier implementation will be used.
Info
Before you begin make sure to configure your Security Token Service (STS) and start it. In addition, when working with real-time notifications, you need to define the JMS map message payload in the following format.
"payloadData": [
{
"name": "revokedToken",
"type": "STRING"
},
{
"name": "ttl",
"type": "STRING"
}
]
-
Navigate to the
<MGW_HOME>/conf/micro-gw.conf
file and add the following configuration.[tokenRevocationConfig] [tokenRevocationConfig.realtime] enableRealtimeMessageRetrieval = true jmsConnectionTopic = "tokenRevocation" jmsConnectioninitialContextFactory = "wso2mbInitialContextFactory" jmsConnectionProviderUrl= "amqp://admin:admin@carbon/carbon?brokerlist='tcp://localhost:5672'" jmsConnectionUsername = "" jmsConnectionPassword = "" [tokenRevocationConfig.persistent] enablePersistentStorageRetrieval = true type = "default" endpointURL = "https://localhost:9443/internal/data/v1" username = "admin" password = "admin"
[tokenRevocationConfig] [tokenRevocationConfig.realtime] enableRealtimeMessageRetrieval = true jmsConnectionTopic = "tokenRevocation" jmsConnectioninitialContextFactory = "wso2mbInitialContextFactory" jmsConnectionProviderUrl= "amqp://admin:admin@carbon/carbon?brokerlist='tcp://localhost:5672'" jmsConnectionUsername = "" jmsConnectionPassword = "" [tokenRevocationConfig.persistent] enablePersistentStorageRetrieval = false type = "default" endpointURL = "https://localhost:9443/internal/data/v1" username = "admin" password = "admin"
[tokenRevocationConfig] [tokenRevocationConfig.realtime] enableRealtimeMessageRetrieval = false jmsConnectionTopic = "tokenRevocation" jmsConnectioninitialContextFactory = "wso2mbInitialContextFactory" jmsConnectionProviderUrl= "amqp://admin:admin@carbon/carbon?brokerlist='tcp://localhost:5672'" jmsConnectionUsername = "" jmsConnectionPassword = "" [tokenRevocationConfig.persistent] enablePersistentStorageRetrieval = true type = "default" endpointURL = "https://localhost:9443/internal/data/v1" username = "admin" password = "admin"
Realtime configurations¶
Property Description enableRealtimeMessageRetrieval
This property is disabled by default. Set this property to true
if you want to enable Real-time Notifications.jmsConnectionTopic
This is the name of the topic in the JMS Message Broker that WSO2 API Microgateway listens to in order to identify messages related to revoked tokens. jmsConnectioninitialContextFactory
jmsConnectionProviderUrl
jmsConnectionUsername
jmsConnectionPassword
Similar to jmsConnectionTopic
these are also JMS related configuration. As you can't use a custom implementation when using Real-time Notifications, you will not need to change these configurations.Persistent configurations¶
Property Description enablePersistentStorageRetrieval
Set this property to true
if you want enable Persistent Notifications.type
This property is set to "default"
in the default configuration, so that you can use WSO2 API Manager eventhub as the default persistent storage. If you are using any other persistent storage, other thandefault
, you need to define your custom implementation in the<MGW_PROJECT>/extensions/token_revocation_extension.bal
file. Thereafter, you need to name set a preferred type name in this property.hostname
The default value is https://localhost:9443/internal/data/v1
. However, you can use etcd version 2,3 (<etcd-server-access-URL>/v3/keys/jti/
) or even another persistent storage of your choice.username
Enter the username of your persistent storage server (e.g., etcd server). The default value for the etcd server is "root". password
Enter the password of your persistent storage server (e.g., etcd server). The default value for the etcd server is "root". Note
When working with persistent notifications, if you introduced new configurations in your custom implementation, then you have to provide the corresponding values for those properties in the
<MGW_HOME>/conf/micro-gw.conf
file under the[tokenRevocationConfig.persistent]
section. -
Generate a JWT token. Use one of the following methods to generate your JWT token.
- Use any third party secure token service (STS) You need to add the public certificate of the token service that you used to sign the JWT token to the trust store of the WSO2 API Microgateway. The JWT should have the sub, aud, exp, and jti claims in order to be successfully validated with WSO2 API Microgateway.
- Use WSO2 API Manager. Obtain a JWT token using the WSO2 API Manager .
-
Extract the jti from the JWT token via the https://jwt.io site.
-
Start WSO2 API Manager or if you select etcd/other service as the persistent storage, configure and start the persistent storage service.
Click here for instructions to configure the etcd server.
-
Download the etcd distribution based on your OS and unzip it. In this example, let's work with etcd v3.3.13 .
-
Navigate to the unzipped etcd distribution and start the etcd server.
cd <etcd_HOME> ./etcd
The following is a sample message that appear.
2019-05-23 19:09:18.921356 I | embed: ready to serve client requests
Note:
If you are working in a production environment, start the etcd server with HTTPS enabled../etcd --name infra0 --data-dir infra0 --cert-file=<PATH_TO_CERT>/server.crt --key-file=<PATH_TO_CERT>/server.key --advertise-client-urls=https://localhost:2379 --listen-client-urls=https://localhost:2379
-
Setup the required authentication with the service as follows:
-
Create a user.
./etcdctl user add <username>
./etcdctl user add root
New password: User <username> created
-
Create a user role.
./etcdctl role add <role_name>
./etcdctl role add root
Role <role_name> created
-
Assign the user to the user role.
./etcdctl user grant <username> --roles <role_name>
./etcdctl user grant root --roles root
User <username> updated
-
Enable user authentication.
./etcdctl auth enable
Authentication Enabled
-
-
Optionally create a directory in the etcd server to store the revoked JWT IDs (jti). This directory can have any name (e.g., jti, jwt) however you have to add this directory name to the
hostname
property in persistent storage configuration../etcdctl -u <username> mkdir <directory_name>
./etcdctl -u root mkdir jti
-
Store the key value pair in the etcd server.
./etcdctl -u <username> set <jti> <ttl>
./etcdctl -u root set "3ad5672a-afca-4387-9ec5-fcf28785f803" 3600
<jti>
- Enter the JWT ID (jti) that corresponds to the JWT token.<ttl>
- Enter the time-to-live (TTL) respective to the revoke token in milliseconds.<username>
- Username of the user created in previous steps.
Info
If you want to check whether you have stored your key-value pair correctly, run the following command.
./etcdctl -u <username> get <jti>
./etcdctl -u root get 3ad5672a-afca-4387-9ec5-fcf28785f803
-
-
Establish security between the persistent storage (etcd server), WSO2 API Microgateway, and the STS.
Note
This is only required if you are working in a production environment.
- Create a self-signed certificate for the persistent storage.
- Add the self-signed certificate to the Ballerina Trust Store (
ballerinaTruststore.p12
) in the WSO2 API Microgateway project and to the Client Trust Store (client-truststore.jks
) in the STS (e.g., WSO2 API Manager).
-
Create and publish an API.
Note
This step is only required if you do not already have an existing API.
For this example, let's skip this step and use the Petstore OpenAPI.
-
Initialize an API Microgateway project (e.g.,
petstore
).micro-gw init <project-name>
micro-gw init petstore
Project 'petstore' is initialized successfully.
-
Build the WSO2 API Microgateway project (e.g., petstore).
- Add an API or multiple APIs to the project.
Navigate to the
/petstore/api_definitions
directory. Add the API definition(s) to this directory. For this example, let's add the petstore open API definition. -
Navigate to the
<MGW_HOME>/bin
directory and run the following command.micro-gw build <project-name>
micro-gw build petstore
Generating sources...[DONE] Compiling source wso2/petstore:3.2.0 Creating balos target/balo/petstore-2020r1-java8-3.2.0.balo Running Tests wso2/petstore:3.2.0 No tests found Generating executables target/bin/petstore.jar BUILD SUCCESSFUL Target: <PROJECT_LOCATION>petstore/target/petstore.jar
This creates an executable file (
/petstore/target/petstore.jar
) that you can use to expose the API via WSO2 API Microgateway.
- Add an API or multiple APIs to the project.
Navigate to the
-
Start WSO2 API Microgateway.
gateway <path-to-MGW-executable-file>
gateway /Users/kim/Downloads/TestProj/petstore/target/petstore.jar
INFO [wso2/gateway/src/gateway/utils] - [TokenRevocationJMS] [-] subscriber service for token revocation is started [ballerina/http] started HTTPS/WSS listener 0.0.0.0:9096 [ballerina/http] started HTTP/WS listener 0.0.0.0:9090 INFO [wso2/gateway/src/gateway/utils] - [APIGatewayListener] [-] HTTP listener is active on port 9090 [ballerina/http] started HTTPS/WSS listener 0.0.0.0:9095 INFO [wso2/gateway/src/gateway/utils] - [APIGatewayListener] [-] HTTPS listener is active on port 9095 INFO [wso2/gateway/src/gateway/utils] - [RevokedJwtRetrievalTask] [-] Revoked jwt retrieval successful. Stopping the timer task ... INFO [wso2/gateway/src/gateway/utils] - [RevokedJwtRetrievalTask] [-] Revoked jwt retrieval task stopped successfully
-
Test the synchronization process of token revocation.
-
Send the revoke request using the extracted jti as the token.
curl -k -v -d "token=<jti>" -H "Authorization: Basic <base64-encoded-string>" -H "Content-Type: application/x-www-form-urlencoded" https://localhost:8243/revoke
curl -k -v -d "token=1e41eb69-b134-4158-ba16-9449ecaa2b3b" -H "Authorization: Basic U01OYVM0Tkg1UlJKSFJONDVoSzcxWElVbXdNYTo4ajRqTHFBUDZDNjNSTkFTVTdMZDEyeVUxbHNh" -H "Content-Type: application/x-www-form-urlencoded" https://localhost:8243/revoke
<jti>
- Enter the JWT ID (jti) that corresponds to the JWT token, which you obtained in step 3 , that you want to revoke.<base64-encoded-string>
- Use a base64 encoder (e.g., https://www.base64encode.org/ ) to encode your client ID and client secret using the following format:<clientId>:<clientSecret>
Thereafter, enter the encoded value for this parameter.
The following response can be seen via the WSO2 API Microgateway console.
2019-06-14 17:20:45,636 DEBUG [wso2/gateway] - [TokenRevocationJMS] [-] token revoked jms Message Received 2019-06-14 17:20:45,638 DEBUG [wso2/gateway] - [TokenRevocationJMS] [-] Successfully added to revoked token map
-
Use the revoked JWT token to send a request to WSO2 API Microgateway.
curl -k -i -H "Authorization: Bearer <JWT-token>" https://localhost:9095/petstore/v1/pet/findByStatus?status=available
curl -k -i -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5UQXhabU14TkRNeVpEZzNNVFUxWkdNME16RXpPREpoWldJNE5ETmxaRFUxT0dGa05qRmlNUT09In0=.eyJhdWQiOiJodHRwOlwvXC9vcmcud3NvMi5hcGltZ3RcL2dhdGV3YXkiLCJzdWIiOiJhZG1pbiIsImFwcGxpY2F0aW9uIjp7Im93bmVyIjoiYWRtaW4iLCJ0aWVyIjoiVW5saW1pdGVkIiwibmFtZSI6Ikp3dFRlc3QiLCJpZCI6Mn0sInNjb3BlIjoiYW1fYXBwbGljYXRpb25fc2NvcGUgZGVmYXVsdCIsImlzcyI6Imh0dHBzOlwvXC9sb2NhbGhvc3Q6OTQ0M1wvb2F1dGgyXC90b2tlbiIsImtleXR5cGUiOiJQUk9EVUNUSU9OIiwic3Vic2NyaWJlZEFQSXMiOltdLCJjb25zdW1lcktleSI6IkpGTjJiRkJyVzdJR2NBaVoydWVkUzM2UjdBY2EiLCJleHAiOjE1NjA1MTY1ODUsImlhdCI6MTU2MDUxMjk4NSwianRpIjoiM2FkNTY3MmEtYWZjYS00Mzg3LTllYzUtZmNmMjg3ODVmODAzIn0=.NVez5rLf2H05AeuAnelDSiDSqj0VwD8A-KtOKr3GxxnelpTM14iyk_k9uyGdsHQ50t9uemowwTCTR2FRo6aOVg3o-RBHzQx2BQEa0VH6JNN83KS0ySkIxjTbNVyCHbFMgFpK0xnhoJyZwnGYYbozwHv2MTJXKdMBose-PclIAgoqNFWDJfYD1YWkdKzeH7QSYnVl6cJWo562PER9a141ydL1jh0snz8QEGKA25PmuvkZ33ydnXSlV1PIBNiHSWL-gTlCmapcPpRqJ8gG8Ld_BGg5QHvqx8YQRTT9p_AHOrhXm-i02IKxYT0zBs6f6y9YDo3F6OeWdmDzItJu14xeqA==" https://localhost:9095/petstore/v1/pet/findByStatus?status=available
Response in the Microgateway Console.
2019-06-14 17:25:27,711 DEBUG [wso2/gateway] - [AuthnFilter] [-] Non-OAuth token found. Calling the auth scheme : jwt 2019-06-14 17:25:27,711 DEBUG [wso2/gateway] - [AuthnFilter] [-] Processing request with the Authentication handler chain 2019-06-14 17:25:27,712 DEBUG [ballerina/http] - Trying to authenticate with the auth provider: jwt 2019-06-14 17:25:27,780 DEBUG [ballerina/auth] - Add authenticated user :admin to the cache 2019-06-14 17:25:27,781 DEBUG [wso2/gateway] - [JWTAuthProvider] [-] jwt found from the jwt cache 2019-06-14 17:25:27,781 DEBUG [wso2/gateway] - [JWTAuthProvider] [-] jti claim found in the jwt 2019-06-14 17:25:27,782 DEBUG [wso2/gateway] - [JWTAuthProvider] [-] Checking for the JTI in the gateway invalid revoked token map. 2019-06-14 17:25:27,782 DEBUG [wso2/gateway] - [JWTAuthProvider] [-] JTI token found in the invalid token map. 2019-06-14 17:25:27,782 DEBUG [wso2/gateway] - [JWTAuthProvider] [-] JWT Authentication Handler returned with value : false 2019-06-14 17:25:27,783 DEBUG [wso2/gateway] - [JWTAuthProvider] [-] JWT Token is revoked 2019-06-14 17:25:27,783 DEBUG [wso2/gateway] - [AuthnFilter] [-] Authentication handler chain returned with value : false 2019-06-14 17:25:27,784 DEBUG [wso2/gateway] - [AuthnFilter] [-] Removed header : Authorization from the request
Response in the STS (e.g., WSO2 API Manager).
HTTP/1.1 401 Unauthorized content-type: application/json content-length: 146 server: ballerina/0.990.5 date: Fri, 14 Jun 2019 17:25:27 +0530 {"fault":{"code":900901, "message":"Invalid Credentials", "description":"Invalid Credentials. Make sure you have given the correct access token"}}
-