In this post we will discuss how to use external implementation for JWT generating logic.
Recently we introduce accessToken to generateToken() method available in AbstractJWTGenerator class which implemented TokenGenerator.
With this change custom JWT generator can generate JWT based on the API access token as well.
We didn't changed method signature of populateStandardClaims(). But followings were changed.
-TokenGenerator.generateToken(APIKeyValidationInfoDTO keyValidationInfoDTO, String apiContext,String version, String accessToken) throws APIManagementException
-AbstractJWTGenerator.buildBody(APIKeyValidationInfoDTO keyValidationInfoDTO, String apiContext, String version, String accessToken)
-AbstractJWTGenerator.populateCustomClaims(APIKeyValidationInfoDTO keyValidationInfoDTO, String apiContext,String version, String accessToken)
New method:
public String generateToken(APIKeyValidationInfoDTO keyValidationInfoDTO, String apiContext,String version, String accessToken) throws APIManagementException.
Sample CustomTokenGenerator code would be something like this. There you can implement your own claim generator.
package org.wso2.carbon.test;
import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO;
import org.wso2.carbon.apimgt.impl.token.JWTGenerator;
import org.wso2.carbon.apimgt.api.*;
import java.util.Map;
public class CustomTokenGenerator extends JWTGenerator {
public Map populateStandardClaims(APIKeyValidationInfoDTO keyValidationInfoDTO, String apiContext, String version)
throws APIManagementException {
Map claims = super.populateStandardClaims(keyValidationInfoDTO, apiContext, version);
boolean isApplicationToken =
keyValidationInfoDTO.getUserType().equalsIgnoreCase(APIConstants.ACCESS_TOKEN_USER_TYPE_APPLICATION) ? true : false;
String dialect = getDialectURI();
if (claims.get(dialect + "/enduser") != null) {
if (isApplicationToken) {
claims.put(dialect + "/enduser", "null");
claims.put(dialect + "/enduserTenantId", "null");
} else {
String enduser = claims.get(dialect + "/enduser");
if (enduser.endsWith("@carbon.super")) {
enduser = enduser.replace("@carbon.super", "");
claims.put(dialect + "/enduser", enduser);
}
}
}
return claims;
}
public Map populateCustomClaims(APIKeyValidationInfoDTO keyValidationInfoDTO, String apiContext, String version, String accessToken)
throws APIManagementException {
System.out.println("************************************************************************Access Token is :"+accessToken );
boolean isApplicationToken =
keyValidationInfoDTO.getUserType().equalsIgnoreCase(APIConstants.ACCESS_TOKEN_USER_TYPE_APPLICATION) ? true : false;
if(getClaimsRetriever() != null) {
if (isApplicationToken) {
return null;
}else {
return super.populateCustomClaims(keyValidationInfoDTO,apiContext,version,accessToken);
}
}
return null;
}
}
Build this class and add jar file to /repository/components/lib/ directory of the product.
Then add the element to specify which implementation should be used as the JWTGenerator.
This should come under section in api-manager.xml.
Also JWT generation should be enabled at this time.
Recently we introduce accessToken to generateToken() method available in AbstractJWTGenerator class which implemented TokenGenerator.
With this change custom JWT generator can generate JWT based on the API access token as well.
We didn't changed method signature of populateStandardClaims(). But followings were changed.
-TokenGenerator.generateToken(APIKeyValidationInfoDTO keyValidationInfoDTO, String apiContext,String version, String accessToken) throws APIManagementException
-AbstractJWTGenerator.buildBody(APIKeyValidationInfoDTO keyValidationInfoDTO, String apiContext, String version, String accessToken)
-AbstractJWTGenerator.populateCustomClaims(APIKeyValidationInfoDTO keyValidationInfoDTO, String apiContext,String version, String accessToken)
New method:
public String generateToken(APIKeyValidationInfoDTO keyValidationInfoDTO, String apiContext,String version, String accessToken) throws APIManagementException.
Sample CustomTokenGenerator code would be something like this. There you can implement your own claim generator.
package org.wso2.carbon.test;
import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO;
import org.wso2.carbon.apimgt.impl.token.JWTGenerator;
import org.wso2.carbon.apimgt.api.*;
import java.util.Map;
public class CustomTokenGenerator extends JWTGenerator {
public Map
throws APIManagementException {
Map
boolean isApplicationToken =
keyValidationInfoDTO.getUserType().equalsIgnoreCase(APIConstants.ACCESS_TOKEN_USER_TYPE_APPLICATION) ? true : false;
String dialect = getDialectURI();
if (claims.get(dialect + "/enduser") != null) {
if (isApplicationToken) {
claims.put(dialect + "/enduser", "null");
claims.put(dialect + "/enduserTenantId", "null");
} else {
String enduser = claims.get(dialect + "/enduser");
if (enduser.endsWith("@carbon.super")) {
enduser = enduser.replace("@carbon.super", "");
claims.put(dialect + "/enduser", enduser);
}
}
}
return claims;
}
public Map
throws APIManagementException {
System.out.println("************************************************************************Access Token is :"+accessToken );
boolean isApplicationToken =
keyValidationInfoDTO.getUserType().equalsIgnoreCase(APIConstants.ACCESS_TOKEN_USER_TYPE_APPLICATION) ? true : false;
if(getClaimsRetriever() != null) {
if (isApplicationToken) {
return null;
}else {
return super.populateCustomClaims(keyValidationInfoDTO,apiContext,version,accessToken);
}
}
return null;
}
}
Build this class and add jar file to /repository/components/lib/ directory of the product.
Then add the
This should come under
Also JWT generation should be enabled at this time.
<APIConsumerAuthentication> .... <TokenGeneratorImpl>org.wso2.carbon.test.CustomTokenGenerator</TokenGeneratorImpl> .... </APIConsumerAuthentication>Restart the server with : Linux/Unix : sh wso2server.sh Windows : wso2server.bat Then when you invoke APIs you will see access token getting printed.
Hello Sanjeewa,
ReplyDeleteCould you please let me know which jar files we need to use to satisfy below failure of import? And how to deploy and execute code?
import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO;
import org.wso2.carbon.apimgt.impl.token.JWTGenerator;
import org.wso2.carbon.apimgt.api.*;
Thank you.
Sayali
Please add following dependencies to your pom file.
ReplyDeleteAnd note that versions can change with API Manager product version. You can search for impl and api jars in your pack to get exact version numbers.
org.wso2.carbon.apimgt
org.wso2.carbon.apimgt.impl
4.3.0-SNAPSHOT
org.wso2.carbon.apimgt
org.wso2.carbon.apimgt.api
4.3.0-SNAPSHOT
Hi Sanjeewa,
ReplyDeleteIs there a way configure multiple (application-wise) TokenGeneratorImpl classes in api-manager.xml or is it one per the WSO2 instance?
Thanks,
Akshit.
Hi Akshit,
ReplyDeleteNo there is no way to generate tokens per application. But like i mentioned if need you can call external service with application details and generate custom response if need. You can implement your own logic to generate application based JWT.
Thanks,
sanjeewa.