JSON Web Token (JWT) is used to represent claims that are transferred between two parties such as the enduser and the backend.
A claim is an attribute of the user that is mapped to the underlying user store. It is encoded as a JavaScript Object Notation (JSON) object that is used as the payload of a JSON Web Signature (JWS) structure, or as the plain text of a JSON Web Encryption (JWE) structure. This enables claims to be digitally signed.
A set of claims is called a dialect (e.g., http://wso2.org/claims
). The general format of a JWT is {token infor}.{claims list}.{signature}
. The API implementation uses information such as logging, content filtering and authentication/authorization that is stored in this token. The token is Base64-encoded and sent to the API implementation in a HTTP header variable. The JWT is self-contained and is divided into three parts as the header, the payload and the signature. For more information on JWT, see http://openid.net/specs/draft-jones-json-web-token-07.html#anchor3 .
To authenticate endusers, the API Manager passes attributes of the API invoker to the backend API implementation using JWT. In most production deployments, service calls go through the API Manager or a proxy service. If you enable JWT generation in the API Manager, each API request will carry a JWT to the back-end service. When the request goes through the API manager, the JWT is appended as a transport header to the outgoing message. The back-end service fetches the JWT and retrieves the required information about the user, application, or token.
...
Before passing enduser attributes, you enable and configure the JWT implementation in the <APIM_HOME>/repository/conf/api-manager.xml
file. The relevant elements are described below. If you do not configure these elements, they take their default values.
Element | Description | Default Value |
---|---|---|
<EnableTokenGeneration> | Set this value to true to enable |
JWT |
. | false | ||||||||||||||
<SecurityContextHeader/> | The name of the HTTP header to which the JWT is attached. | X-JWT-Assertion | |||||||||||||
<ClaimsRetrieverImplClass/> | By default, the
By default, the following are encoded to the JWT:
In addition, you can also write your own class by extending the interface
| org.wso2.carbon.apimgt.impl.token.DefaultClaimsRetriever | |||||||||||||
<ConsumerDialectURI/> | The dialect URI under which the user's claims are be looked for. Only works with the default value of The JWT token contains all claims define in the
| http://wso2.org/claims | |||||||||||||
<SignatureAlgorithm/> | The signing algorithm used to sign the JWT. The general format of the JWT is This element can have only two values- the default value, which is SHA256WITHRSA or NONE. | SHA256WITHRSA |
Tip |
---|
You can use TCPMon or API Gateway debug logs to capture JWT token header withenduser details. To enable gateway DEBUG logs for wire messages,
|
...
The JWT that is generated by default (see example above) has predefined attributes that are passed to the backend. These include basic application-specific details, subscription details, and user information that are defined in the JWT generation class that comes with the API Manager by the name org.wso2.carbon.apimgt.impl.token.JWTGenerator
. If you want to pass additional attributes to the backend with the JWT or completely change the default JWT generation logic, do the following:
Write your own custom JWT implementation class by extending the default
JWTGenerator
class. A typical example of implementing your own claim generator is given below. It implements thepopulateCustomClaims()
method to generate some custom claims and adds them to the JWT.Code Block language java 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 { Long time = System.currentTimeMillis(); String text = "This is custom JWT"; Map map = new HashMap(); map.put("current_timestamp", time.toString()); map.put("messge" , text); return map; } }
- Build your class and add the JAR file to
<APIM_HOME>/repository/components/lib
directory. Add your class in the <TokenGeneratorImpl> element of the
<APIM_HOME>/repository/conf/api-manager.xml
file.Code Block language xml <APIConsumerAuthentication> .... <TokenGeneratorImpl>org.wso2.carbon.test.CustomTokenGenerator</TokenGeneratorImpl> .... </APIConsumerAuthentication>
- Set the
<EnableTokenGeneration>
element to true in theapi-manager.xml
file. - Restart the server.