I have a structure with APIM, IS and Microintegrator. Configured APIM to pass attributes to backend via X-JWT-Assertion header.
Now I need to decode this JWT into Json format to use some claims.
I tried it with the function:
<property expression="base64Decode(get-property('JWT_HEADER'))" name="decoded"/>
but it returns the scrambled data.
enter image description here
Does anyone know how I can do decoding?
Thanks.
A JWT token contains three parts separated by dots (.) as follows [JWT.io]
Header
Body
Signature
If you are trying to access the claims, you have to split the body part and then decode it. Otherwise, it will result in an unreadable format as you have mentioned above.
The following is a sample expression to split and decode the Body of the JWT Token
<property name="assertion" expression="$trp:X-JWT-Assertion" />
<!-- split the body content using substring functions -->
<property name="decoded" expression="base64Decode(fn:substring-before(fn:substring-after($ctx:assertion, '.'), '.'))" />
<log level="custom">
<property name="decoded-body" expression="$ctx:decoded" />
</log>
Related
There is a legacy Rest service which has its own authentication architecture (self-owned db to store user information and using basic auth). Other rest services are all using Keycloak as IdP (with OpenID as token).
I'm trying to use WSO2 API manager before the legacy Rest API that it can authenticate calls using OpenID just as other api services. I found there's a guide saying how to pass the end user attributes to the back-end service and also how to pass a custom authorization token to the back-end service.
And now, I want to know whether it is possible to retrieve the caller's id (viz., the end user id) in a sequence or not? It means I can get the end user's id from a property, modify it and then set it to the Authorization header.
Thus, the complete process seems as:
An end user generates a JWT token from Keycloak
The end user calls an api published by API Manager with the token
API Manager retrieves the end user's userid and sets it into the Authorization header
API Manager calls the back-end service with the changed Authorization header
You can try implementing the following sequence as an in-sequence to your API. The following sequence retrieves the End User ID using the Synapse Properties and assigns it to the Authorization Header.
<?xml version="1.0" encoding="UTF-8"?><sequence xmlns="http://ws.apache.org/ns/synapse" name="username-header">
<property name="userid" expression="$ctx:api.ut.userName"/>
<!-- property name="userid" expression="$ctx:api.ut.userId"/ -->
<log level="custom">
<property name="User ID" expression="$ctx:userid" />
</log>
<property name="Authorization" expression="$ctx:userid" scope="transport" action="set" />
</sequence>
Furthermore, you can also try using the following Synapse properties, if the above doesn't fulfil your requirement.
api.ut.username
api.ut.userId
If you are trying to read the end user's ID from the Backend JWT token that is generated by the API Manager during the API invocation, then it is required to come up with an extended mediation sequence, to read and decode the Token, and then to extract the information. Given below is a sample (not complete) if the requirement is as described above
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="admin--AssertionAPI:v1.0.0--In">
<property name="assertion" expression="$trp:X-JWT-Assertion" />
<log level="custom">
<property name="Assertion" expression="$trp:X-JWT-Assertion" />
</log>
<property name="Body" expression="base64Decode(fn:substring-before(fn:substring-after($ctx:assertion, '.'), '.'))" />
<log level="custom">
<property name="body" expression="$ctx:Body" />
</log>
<!-- use script mediator to access required properties -->
<!-- and set the value as a header -->
</sequence>
I am using wso2 API manager 3.2 and in my API there are some headers and Query Parameter.
My API has some path variable in URL in this way
http://example.com/data/readsomeData/{entityId}/{someId}
for the path variable I use the following mediator
<property name="REST_URL_POSTFIX" scope="axis2" action="remove"/>
and it works fine.
also I change some of incoming header's name . For example incoming header is IN_HEADER , I translate it to OUT_HEADER ,my backend expects OUT_HEADER.
I also use this mediator
<property name="IN_HEADER" expression="get-property('transport', 'IN_HEADER')"/>
<property name="OUT_HEADER" expression="get-property('IN_HEADER')" scope="transport"/>
<property name="IN_HEADER" scope="transport" action="remove"/>
It also works fine too.
The given API describe above also has some optional query parameters (limit, max, min) . For example if I use limit=10 in my API, I have to get 10 records, with out limit I get just one record.
In WSO2 API Manager Publisher I defined the above query parameters as the other parameters.
The problem is when I use each of query parameter I get the result same as the way I do not use the query parameters. I get only one record.
I think the API manager does not pass the query parameters to backend.
I don't know this problem related to the mediator I use or not!
You can approach this in a few different ways, below examples should also work on 3.2.0.
Because you remove the REST_URL_POSTFIX the APIM also removes the query parameters.
So option 1:
You could do something similar to what you did for the other headers.
Grab the query parameters and add them as headers for further use. (the $url shorthand should also be available in 3.2.0 as far as I know - it grabs a query parameter by name.)
<property name="limit" expression="$url:limit" scope="transport"/>
<property name="min" expression="$url:min" scope="transport"/>
<property name="max" expression="$url:max" scope="transport"/>
Or you could grab the query parameters from your URL and put them back after removing the POSTFIX.
<property name="newUrlPostfix" expression="substring after($axis2:REST_URL_POSTFIX, '?')"/>
<property name="REST_URL_POSTFIX" scope="axis2" action="remove"/>
<property name="REST_URL_POSTFIX" scope="axis2" expression="concat('?', $ctx:newUrlPostfix"/>
I have a requirement to parse JSON response which contain array of products(P1,P2,P3,etc.). Each product contains multiple information like name, type, cost, etc.
I need to read each product one by one and append additional data got from the another service into an new JSON output. I am thinking of using ForEach component of WSO2 ESB to iterate each product one by one.
Problem is that ForEach component uses ForEachExpression which expects XML expression in the configuration.
Please suggest on the method to parse array of JSON response one by one in WSO2 ESB.
/Abhishek
Can use both Iterate or ForEach mediator for iterating the JSON array, since both are content aware mediators and support JSON.
Which one to use depends upon the specific usecase as Iterate provides the capability to use call / callout / send mediators in the sequence whereas ForEach doesn´t allow it.
For the below given sample JSON request, the following iteration works and the JSON array and objects can be referred like the same.
{
"products":[
{
"product":{
"id":"1234",
"size":"20",
"quantity":"1",
"price":"990",
"type":"Electronics",
"store":{
"id":"001"
}
}
}
]
}
<iterate expression="//products" id="PRD_ITR">
<target>
<sequence>
<sequence key="Product_Enrich_Sequence_s"/>
<!-- For example, Switching sequence based on the product type -->
<switch source="//products/product/type">
<case regex="Computer">
<sequence key="Computer_Product_Enrich_Sequence_s"/>
</case>
<case regex="Mobile">
<sequence key="Mobile_Product_Enrich_Sequence_s"/>
</case>
<case regex="Grocery">
<sequence key="GR_Product_Enrich_Sequence_s"/>
</case>
<default>
<!-- default stuff --!>
</default>
</switch>
</sequence>
</target>
</iterate>
FYR
https://docs.wso2.com/display/ESB490/Iterate+Mediator
https://docs.wso2.com/display/ESB490/ForEach+Mediator
Note: tested in WSO2 ESB 4.9.0
I have the config with development and production sections. This sections contain the URLs of backends. In my inSequence i need it to Callout to these backends several times per request.
<config>
<env>prod</env>
<backend env="prod">http://localhost:1234/</backend>
<backend env="dev">http://localhost:2345/</backend>
</config>
I read this config from Local Entry (as XML) and want to set Callout's URL as an Property.
I don't want to hardcode these backends inside my code with "Switch" statement, because it's possible to use more than two environments.
Could you please show me an example?
Thank you.
You can read xml file in registry. Simply define property of OM type like this:
<property name="test" expression="get-property('registry','conf:/test.xml')" scope="default" type="OM" />
Then you can see the value by logging like this:
<log level="custom"> <property name="test.b" expression="$ctx:test//b" /> </log>
And in the xml file that you have put in the root of registry, you would fill it like:
<a>Hello<b>WSO2</b></a>
I have learned it from this link.
I found the answer. According to source of Callout mediator:
CalloutMediator.java
It uses "To" header if URL is not specified.
Can some one point me to a working example of xsl transformation using the proxy services xslt mediator option.
Basically, my requirement is, i will have a request where i will get some data which determines the routing and after that from other elements of requested data i have to re frame soap request to trigger another bpel service.
Please let me know the better approach to this.
You can very well use XSLT transformation in your sequence, using XSLT Mediator.
In your sequence file you can specify the XSLT file to tranform the request. Sample sequence code snippet:
<sequence xmlns="http://ws.apache.org/ns/synapse" name="SampleInterceptorSequence">
<in>
<log level="full" category="DEBUG">
<property name="sequence" value="inSequence-Request Before XSLT" />
</log>
<xslt key="RequestTranformerXSLT" />
<log level="full" category="DEBUG">
<property name="sequence" value="inSequence-Request After XSLT" />
</log>
<send>
<endpoint key="MyActualServiceEPR" />
</send>
</in>
Your xslt would contain the style for the actual request to be formed for hitting the end point reference.
Further if you can check this nice article of web service chaining to get a real time idea of xslt mediation.
Web Service Chaining from WSO2 ESB Developers
Hope this helps.
Thanks.
Find the sample below..
http://wso2.org/project/esb/java/4.0.0/docs/samples/message_mediation_samples.html#Sample8