Custom JWT Generator in WSO2 API Manager
Create a custom JWT generator with WSO2 API Manager (2.6.0)
Join the DZone community and get the full member experience.
Join For FreeThis is yet another article on generating custom JWT in WSO2 API Manager. For details please read the official documentation.
Software
For this tutorial, you will only need the following product.
WSO2 API Manager (2.6.0)
Make sure that you have Java installed in your system.
Creating a Maven Project
Let's create a very simple Maven project. Here is the pom.xml of the project.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.anupam.jwt</groupId>
<artifactId>MyJWTGenerator</artifactId>
<packaging>jar</packaging>
<version>1.0.0</version>
<name>MyJWTGenerator</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.wso2.carbon.apimgt</groupId>
<artifactId>org.wso2.carbon.apimgt.keymgt</artifactId>
<version>6.1.66</version>
<scope>provided</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>wso2-nexus</id>
<name>WSO2 internal Repository</name>
<url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>ignore</checksumPolicy>
</releases>
</repository>
</repositories>
</project>
Custom JWT Generator
To create a custom JWT generator, you will need to create a class extending the following superclass.
org.wso2.carbon.apimgt.keymgt.token.AbstractJWTGenerator
In this tutorial, I am going to add three extra claims (access_token, prop_1 & prop_2) to the JWT, along with the default claims of WSO2 API Manager. Here is the custom JWT generator class.
package com.anupam.jwt;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.api.APIManagementException;
import org.wso2.carbon.apimgt.impl.token.ClaimsRetriever;
import org.wso2.carbon.apimgt.keymgt.service.TokenValidationContext;
import org.wso2.carbon.apimgt.keymgt.token.AbstractJWTGenerator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.SortedMap;
public class MyJWTGenerator extends AbstractJWTGenerator {
private static final Log log = LogFactory.getLog(MyJWTGenerator.class);
public MyJWTGenerator() {
}
public Map<String, String> populateStandardClaims(TokenValidationContext validationContext) throws APIManagementException {
Map<String, String> claims = new LinkedHashMap(20);
return claims;
}
public Map<String, String> populateCustomClaims(TokenValidationContext validationContext) throws APIManagementException {
ClaimsRetriever claimsRetriever = this.getClaimsRetriever();
String tenantAwareUserName = validationContext.getValidationInfoDTO().getEndUserName();
SortedMap<String, String> map = claimsRetriever.getClaims(tenantAwareUserName);
map.put("access_token", validationContext.getAccessToken());
map.put("prop_1","Property One");
map.put("prop_2","Property Two");
return map;
}
}
Packing the Class
Generate a jar file.
$ mvn clean install
Copy the jar file and put it in the following directory of WSO2 API Manager.
$ wso2am-2.6.0/repository/components/lib
Configure the Custom JWT Generator
Here is the basic configuration you will need for the custom JWT generator to work in WSO2 API Manager.
Configuration in api-manager.xml
Edit the following information in the api-manager.xml of WSO2 API Manager; it's a mandatory configuration.
wso2am-2.6.0/repository/conf/api-manager.xml
<JWTConfiguration>
<!-- Enable/Disable JWT generation. Default is false. -->
<EnableJWTGeneration>true</EnableJWTGeneration>
<!-- Name of the security context header to be added to the validated requests. -->
<JWTHeader>X-JWT-Assertion</JWTHeader>
<!-- Fully qualified name of the class that will retrieve additional user claims
to be appended to the JWT. If not specified no claims will be appended.If user wants to add all user claims in the
jwt token, he needs to enable this parameter.
The DefaultClaimsRetriever class adds user claims from the default carbon user store. -->
<ClaimsRetrieverImplClass>org.wso2.carbon.apimgt.impl.token.DefaultClaimsRetriever</ClaimsRetrieverImplClass>
<!-- The dialectURI under which the claimURIs that need to be appended to the
JWT are defined. Not used with custom ClaimsRetriever implementations. The
same value is used in the keys for appending the default properties to the
JWT. -->
<ConsumerDialectURI>http://wso2.org/claims</ConsumerDialectURI>
<!-- Signature algorithm. Accepts "SHA256withRSA" or "NONE". To disable signing explicitly specify "NONE". -->
<!--SignatureAlgorithm>SHA256withRSA</SignatureAlgorithm-->
<!-- This parameter specifies which implementation should be used for generating the Token. JWTGenerator is the
default implementation provided. -->
<JWTGeneratorImpl>com.anupam.jwt.MyJWTGenerator</JWTGeneratorImpl>
<!-- This parameter specifies which implementation should be used for generating the Token. For URL safe JWT
Token generation the implementation is provided in URLSafeJWTGenerator -->
<!--<JWTGeneratorImpl>org.wso2.carbon.apimgt.keymgt.token.URLSafeJWTGenerator</JWTGeneratorImpl>-->
</JWTConfiguration>
Note that in JWTGeneratorImpl, we have referred to our custom JWT generator class.
Configuration in log4j.properties File
This is an optional configuration and should not be done in the production environment. Add this property in the log4j.properties file.
wso2am-2.6.0/repository/conf/log4j.properties
log4j.category.org.apache.synapse.transport=DEBUG
Testing
Start the WSO2 API Manager.
$ sh wso2server.sh
Open https://localhost:9443/carbon, and let's fill the default claim values of the admin user as shown below.
Now, deploy the PizzaShack sample API, and let's make a call to any of its resources. In the log, you should see the JWT in the header X-JWT-Assertion we configured in the api-manager.xml file.
Let's copy the value and decode it in https://jwt.io/
Here is the decoded token.
{
"http://wso2.org/claims/organization": "WSO2",
"http://wso2.org/claims/role": [
"Internal/subscriber",
"Internal/creator",
"Application/admin_DefaultApplication_PRODUCTION",
"Internal/publisher",
"Internal/everyone",
"admin"
],
"http://wso2.org/claims/mobile": "1111111111",
"prop_1": "Property One",
"http://wso2.org/claims/givenname": "Administrator",
"prop_2": "Property Two",
"access_token": "e9c342e1-f079-3e37-8c4c-7bc629a60850",
"http://wso2.org/claims/telephone": "1111111111",
"http://wso2.org/claims/im": "admin.admin",
"http://wso2.org/claims/country": "Brazil",
"http://wso2.org/claims/emailaddress": "admin@carbon.super",
"http://wso2.org/claims/lastname": "Administrator",
"http://wso2.org/claims/url": "http://www.porua.com"
}
You can check the extra claims (access_token, prop_1, and prop_2) along with the default claims. This JWT will be passed to the backend implementation of the API in the X-JWT-Assertion header and the backend can extract information from the JWT for farther validation.
Debugging
Debugging is the best way to understand what goes under the hood. Use the IntelliJ IDE (my preference) and create a remote debugging configuration as shown below.
Stop the WSO2 API Manager and restart it with the debug mode enabled.
$ sh wso2server.sh -debug 5000
Put some debug points in the custom JWT generator class. Once you make a request to the PizzaShack API, you should be able to enter in the debug points.
Conclusion
This is a simple custom JWT generator class that I described in the article. This tutorial is completely based on API Manager 2.6.0. If the same custom JWT generator is created for a different version of API Manager, it might not work due to dependency.
Thanks for reading, and please let me know if you could create one.
Opinions expressed by DZone contributors are their own.
Comments