Skip to main content

Passing end-user details from client to real backend endpoint via JWT token

In real-world business system,WSO2 API Manager useful on exposing company APIs, in a secured and controlled manner with the features provided by APIManager as;
  • OAuth support [To secure API invocations]
  • Throttling support [To control API invocations]
  • Monitoring support [To track API usage]
More technically what happening is when a user sends a particular API request,it will goes to WSO2 APIManager node and from there,the request will route to the real implemented back-end endpoint of the particular API and get back the response and returned it to the API invoked user. There can be a use-case,that this back-end endpoint may expect the details of API invoked user as to pass those details to some internal company usage  as;
  • Additional authentication/authorization
  • Track usage data from an internal system.
So how to support above requirement from WSO2 AM.
There comes the use of JSON Web Token[JWT] implementation done inside WSO2 AM. JWT is a means of representing claims to be transferred between two parties. The claims in a JWT are 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, enabling the claims to be digitally signed or MACed and/or encrypted.For get more information on JWT tokens ,please refer this link.
With current JWT token implementation of APIManager,following details will be pass to backend endpoint.

  1. Subscriber Name
  2. Application Name
  3. Tier
  4. End-User Name
  5. API context
  6. Version
  7. Key Type [Production/Sandbox]
  8. User Type[Application Token/User Token]
Below blog content will guide you on how to enable JWT token passing support from APIManager.

Configure WSO2 APIManager to pass JWT token

  1. Enable JWT token generation by uncommenting below configuration and set its value as true from api-manager.xml.
       <EnableTokenGeneration>true</EnableTokenGeneration>

    2. Start the AM server,create,publish API and subscribe it from the APIStore.


    3. Invoke the API and capture the outgoing message from the API Manager.Here its required to 

      monitor transport level header values as JWT token will be pass to backend as a transport header.

      To capture the outgoing message,you can use;

  • By Tcpmon tool in-between APIManager node and backend endpoint.For more info,refer the blog.
  • By enabling  wire logs of APIManager -By updating below configurations into log4j.properties file which can be found from {AM_Home}/repository/conf.If you follow this,you need to restart AM node.
        Uncomment  log4j.category.org.apache.synapse.transport.nhttp.wire=DEBUG
        Update log4j.category.org.apache.synapse.transport=INFO as  
        log4j.category.org.apache.synapse.transport=DEBUG

With capturing APIManager outputting message from one of either above option,you'll see a HTTP header  name as  "X-JWT-Assertion" has append to transport headers.Note the JWT-Assertion header value will contains base64 encoded value.If you capture the outgoing message of    APIM with wirelogs,when you invoke an API,you'll see below logs will be output in APIM with JWT-Assertion.

TID: [0] [AM] [2013-06-29 09:05:05,548] DEBUG {org.apache.synapse.transport.http.headers} -  http-outgoing-1>>X-JWT-Assertion: eyJ0eXAiOiJKV1QiLCJhbGciOiJTSEEyNTZ3aXRoUlNBIiwieDV0IjoiTm1KbU9HVXhNelpsWWpNMlpEUmhOVFpsWVRBMVl6ZGhaVFJpT1dFME5XSTJNMkptT1RjMVpBPT0ifQ==.eyJpc3MiOiJ3c28yLm9yZy9wcm9kdWN0cy9hbSIsImV4cCI6MTM3MjUyMjgwNTE3NywiaHR0cDovL3dzbzIub3JnL2NsYWltcy9zdWJzY3JpYmVyIjoibGFsYWppIiwiaHR0cDovL3dzbzIub3JnL2NsYWltcy9hcHBsaWNhdGlvbmlkIjoiMSIsImh0dHA6Ly93c28yLm9yZy9jbGFpbXMvYXBwbGljYXRpb25uYW1lIjoiRGVmYXVsdEFwcGxpY2F0aW9uIiwiaHR0cDovL3dzbzIub3JnL2NsYWltcy9hcHBsaWNhdGlvbnRpZXIiOiJVbmxpbWl0ZWQiLCJodHRwOi8vd3NvMi5vcmcvY2xhaW1zL2FwaWNvbnRleHQiOiIvYXBpMSIsImh0dHA6Ly93c28yLm9yZy9jbGFpbXMvdmVyc2lvbiI6IjEuMi4zIiwiaHR0cDovL3dzbzIub3JnL2NsYWltcy90aWVyIjoiVW5saW1pdGVkIiwiaHR0cDovL3dzbzIub3JnL2NsYWltcy9rZXl0eXBlIjoiUFJPRFVDVElPTiIsImh0dHA6Ly93c28yLm9yZy9jbGFpbXMvdXNlcnR5cGUiOiJBUFBMSUNBVElPTiIsImh0dHA6Ly93c28yLm9yZy9jbGFpbXMvZW5kdXNlciI6ImxhbGFqaSIsImh0dHA6Ly93c28yLm9yZy9jbGFpbXMvZW5kdXNlclRlbmFudElkIjoiLTEyMzQifQ==.YtVaDtRYtfUkVDvwe9V8oqsXK8OkB4HUhsQS2z3ngWRNjAktSKWlH+Is9T5EQnsg8hrsJQ4nKDdwDWHAUIFxIsb7bX/Y1O+WSLMLZYQ11WVzFaw50BJuqPbL9ZOfux1iRnm4ZbxClVSan72g/w8a05UnCvsGyIh5oCP4RUsAhXo= {org.apache.synapse.transport.http.headers}

To get the end user details,above base64 encoded string need to decode back.NOTE -Above encoded string contains three seperate encoded values.Those three are seperated from '.' [dot] sign. I have highlighted those three strings with different colors in above. You need to decode first two encoded strings to retrieve whole token structure.To decode,you can use www.base64decode.org link.
Once you decode,above first encoded string [green colored] ,you'll get an output as;

{"typ":"JWT","alg":"SHA256withRSA","x5t":"NmJmOGUxMzZlYjM2ZDRhNTZlYTA1YzdhZTRiOWE0NWI2M2JmOTc1ZA=="}
Above will output the token type as JWT and the algorithm used to encode the value as SHA256withRSA.



Then you can decode above second encoded string[red colored],you'll get end-user details as below.

{"iss":"wso2.org/products/am","exp":1372522805177,
"http://wso2.org/claims/subscriber":"lalaji",
"http://wso2.org/claims/applicationid":"1",
 "http://wso2.org/claims/applicationname":"DefaultApplication",
 "http://wso2.org/claims/applicationtier":"Unlimited",
 "http://wso2.org/claims/apicontext":"/api1",
 "http://wso2.org/claims/version":"1.2.3",
"http://wso2.org/claims/tier":"Unlimited",
"http://wso2.org/claims/keytype":"PRODUCTION",
"http://wso2.org/claims/usertype":"APPLICATION",
 "http://wso2.org/claims/enduser":"lalaji",
"http://wso2.org/claims/enduserTenantId":"-1234"}

Such that the overall Token Structure would be like below format;
{"typ":"JWT","alg":"SHA256withRSA","x5t":"NmJmOGUxMzZlYjM2ZDRhNTZlYTA1YzdhZTRiOWE0NWI2M2JmOTc1ZA=="}


{"iss":"wso2.org/products/am","exp":1372522805177,
"http://wso2.org/claims/subscriber":"lalaji",
"http://wso2.org/claims/applicationid":"1",
 "http://wso2.org/claims/applicationname":"DefaultApplication",
 "http://wso2.org/claims/applicationtier":"Unlimited",
 "http://wso2.org/claims/apicontext":"/api1",
 "http://wso2.org/claims/version":"1.2.3",
"http://wso2.org/claims/tier":"Unlimited",
"http://wso2.org/claims/keytype":"PRODUCTION",
"http://wso2.org/claims/usertype":"APPLICATION",
 "http://wso2.org/claims/enduser":"lalaji",
"http://wso2.org/claims/enduserTenantId":"-1234"}


How to pass Access Token used to invoke API to backend


With above JWT token approach,it'll pass the end user details and the invoked API data.But it will not pass the access token to backend. In WSO2 APIManager default behaviour,once an API request comes with an access token include in the Authorization header,it'll first processed the API Key validation handler and drop that access token contained Authorization header from message,without passing it to back-end endpoint.
If you want to pass an OAuth access token to back-end,modify the below configuration in api-manager.xml.

<RemoveOAuthHeadersFromOutMessage>false</RemoveOAuthHeadersFromOutMessage>


Comments

  1. Hi Lalaji,

    Thank you for nice post. However it's not finding much useful because you've not given any steps/information how to publish the project, because of the lack of steps we're unable to execute this example to get JWT assertion from WSO2 APIM. Please help us?

    Thank you, Geeta

    ReplyDelete
  2. Hello Lalaji - I follow the same steps, but I don't see X-JWT-Assertion is getting created, please help!

    ReplyDelete
  3. Is this possible to decode X-JWT-Assertion using OpenSAML library? If yes, could you please guide here ?

    ReplyDelete
  4. Could you please share code which uses Restful Controller to receive the X-JWT-assertion from WSO2 APIM ?

    ReplyDelete
  5. Can you please provide details on how to do the signature validation? Thanks Reshma

    ReplyDelete
  6. I need to pass the some request parameter in JWT(WSO2). Do you have any idea about it how to do so? I have created my own custom JWT generator.

    ReplyDelete
    Replies
    1. No need to create custom JWT. Just map claim in claim configuration of your service provider. https://docs.wso2.com/display/IS500/Adding+New+Claim+Mapping

      Delete

Post a Comment

Popular posts from this blog

Convert an InputStream to XML

For that we can use DocumentBuilder class in java. By using the method parse(InputStream) ; A new DOM Document object will return. InputStream input; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document dc= parser.parse(input); In the above code segment,by using the created Document object,the corresponding XML file for the inputStream can be accessed. References: http://www.w3schools.com/dom/dom_intro.asp http:// download.oracle.com/javase/1.4.2/docs/api/javax/xml/parsers/DocumentBuilder.html

CORS support from WSO2 API Manager 2.0.0

Cross-origin resource sharing (CORS) is a mechanism that allows restricted resources  on a web page to be requested from another domain outside the domain from which the first restricted resource was served. For example, an HTML page of a web application served from http://domain-a.com makes an <img src >  request for a different domain as 'domain-b.com' to get an image via an API request.  For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts as in above example and only allows to make HTTP requests to its own domain. To avoid this limitation modern browsers have been used CORS standard to allow cross domain requests. Modern browsers use CORS in an API container - such as  XMLHttpRequest  or Fetch - to mitigate risks of cross-origin HTTP requests.Thing to  note is it's not only sufficient that the browsers handle client side of cross-origin sharing,but also the servers from which these resources getting need to handl

[WSO2 AM] APIStore User Signup as an approval process

In previous versions of WSO2 APIManager before 1.6.0, it was allowed any user who's accessible the running APIStore come and register to the app.But there will be requirement like,without allowing any user to signup by him/her self alone,first get an approve by a privileged user and then allow to complete app registration.Same requirement can be apply to application creation and subscription creation as well.To fulfill that,we have introduced workflow extension support for  WSO2 APIManager  and you can find the introductory post on this feature from my previous blog post on " workflow-extentions-with-wso2-am-160 " . From this blog-post,I'll explain how to achieve simple workflow integration with default shipped resources with  WSO2 APIManager 1.6.0 and WSO2 Business Process Server 3.1.0 with targeting "user-signup" process. Steps First download the WSO2 APIManager 1.6.0[AM] binary pack from product download page . Extract it and navigate to