To achieve this, We can use custom mediation extensions in APIM 2.0. For more details on Custom mediation, please have a look at this document [1].
When you write your custom sequence, below I have given the synapse source and explanation. In this example, we are going to do our action based on the claim value enduser as an example.
1. First we have set the X-JWT-Assertion header value in to a property named authheader.
<property name="authheader" expression="get-property(' transport','X-JWT-Assertion')" scope="default" type="STRING" description="get X-JWT-Assertion header"/>
Sample X-JWT-Assertion is as below :
X-JWT-Assertion = eyJ0eXAiOiJKV1QiLCJhbGciOiJSUz I1NiIsIng1dCI6ImFfamhOdXMyMUtW dW9GeDY1TG1rVzJPX2wxMCJ9.eyJod HRwOlwvXC93c28yLm9yZ1wvY2xhaW1 zXC9hcHBsaWNhdGlvbnRpZXIiOiJVb mxpbWl0ZWQiLCJodHRwOlwvXC93c28 yLm9yZ1wvY2xhaW1zXC9rZXl0eXBlI joiUFJPRFVDVElPTiIsImh0dHA6XC9 cL3dzbzIub3JnXC9jbGFpbXNcL3Zlc nNpb24iOiIxLjAuMCIsImlzcyI6Ind zbzIub3JnXC9wcm9kdWN0c1wvYW0iL CJodHRwOlwvXC93c28yLm9yZ1wvY2x haW1zXC9hcHBsaWNhdGlvbm5hbWUiO iJEZWZhdWx0QXBwbGljYXRpb24iLCJ odHRwOlwvXC93c28yLm9yZ1wvY2xha W1zXC9lbmR1c2VyIjoiYWRtaW5AY2F yYm9uLnN1cGVyIiwiaHR0cDpcL1wvd 3NvMi5vcmdcL2NsYWltc1wvZW5kdXN lclRlbmFudElkIjoiLTEyMzQiLCJod HRwOlwvXC93c28yLm9yZ1wvY2xhaW1 zXC9zdWJzY3JpYmVyIjoiYWRtaW4iL CJodHRwOlwvXC93c28yLm9yZ1wvY2x haW1zXC90aWVyIjoiVW5saW1pdGVkI iwiaHR0cDpcL1wvd3NvMi5vcmdcL2N sYWltc1wvYXBwbGljYXRpb25pZCI6I jEiLCJodHRwOlwvXC93c28yLm9yZ1w vY2xhaW1zXC91c2VydHlwZSI6IkFQU ExJQ0FUSU9OIiwiZXhwIjoxNDg2NDU 5NTg3LCJodHRwOlwvXC93c28yLm9yZ 1wvY2xhaW1zXC9hcGljb250ZXh0Ijo iXC9qd3RkZWNhcGlcLzEuMC4wIn0=. FE2luGlWKZKZBVjsx7beA4WVlLFJSo HNGgJKm56maK7qddleEzTi/ QhDAdyC47dW+ RgkaJZLSgdvM6ROyW890io7QCOqjJZ g7KnlB54qh2DBoBmAnYbmFZAC08nxn AGpeiy6W4YkYMWlJNW+ lw5D3b3I4NOhyhsIStA9ec9TSQA=
2. Then we have used a script mediator to split and decode our value from the authheader.
var temp_auth = mc.getProperty('authheader'). trim();
var val = new Array();
val= temp_auth.split("\\.");
By the above javascript, we have split the value we get by "." I have highlighted it by Yellow color.
Grean colored value has got our JWT claims.
3. Then we access the 2nd value as val[1] and decode it using Base64.
var auth=val[1];
var jsonStr = Packages.java.lang.String( Packages.org.apache.axiom.om. util.Base64.decode(auth), "UTF-8");
If you decode the particular value using a base64, you wil be able to see the below value.
eyJodHRwOlwvXC93c28yLm9yZ1wvY2 xhaW1zXC9hcHBsaWNhdGlvbnRpZXIi OiJVbmxpbWl0ZWQiLCJodHRwOlwvXC 93c28yLm9yZ1wvY2xhaW1zXC9rZXl0 eXBlIjoiUFJPRFVDVElPTiIsImh0dH A6XC9cL3dzbzIub3JnXC9jbGFpbXNc L3ZlcnNpb24iOiIxLjAuMCIsImlzcy I6IndzbzIub3JnXC9wcm9kdWN0c1wv YW0iLCJodHRwOlwvXC93c28yLm9yZ1 wvY2xhaW1zXC9hcHBsaWNhdGlvbm5h bWUiOiJEZWZhdWx0QXBwbGljYXRpb2 4iLCJodHRwOlwvXC93c28yLm9yZ1wv Y2xhaW1zXC9lbmR1c2VyIjoiYWRtaW 5AY2FyYm9uLnN1cGVyIiwiaHR0cDpc L1wvd3NvMi5vcmdcL2NsYWltc1wvZW 5kdXNlclRlbmFudElkIjoiLTEyMzQi LCJodHRwOlwvXC93c28yLm9yZ1wvY2 xhaW1zXC9zdWJzY3JpYmVyIjoiYWRt aW4iLCJodHRwOlwvXC93c28yLm9yZ1 wvY2xhaW1zXC90aWVyIjoiVW5saW1p dGVkIiwiaHR0cDpcL1wvd3NvMi5vcm dcL2NsYWltc1wvYXBwbGljYXRpb25p ZCI6IjEiLCJodHRwOlwvXC93c28yLm 9yZ1wvY2xhaW1zXC91c2VydHlwZSI6 IkFQUExJQ0FUSU9OIiwiZXhwIjoxND g2NDU5NTg3LCJodHRwOlwvXC93c28y Lm9yZ1wvY2xhaW1zXC9hcGljb250ZX h0IjoiXC9qd3RkZWNhcGlcLzEuMC4w In0=
{"http:\/\/wso2.org\/claims\/ applicationtier":"Unlimited",
"http:\/\/wso2.org\/claims\/ keytype":"PRODUCTION",
"http:\/\/wso2.org\/claims\/ version":"1.0.0",
"iss":"wso2.org\/products\/am" ,
"http:\/\/wso2.org\/claims\/ applicationname":" DefaultApplication",
"http:\/\/wso2.org\/claims\/ enduser":"admin@carbon.super",
"http:\/\/wso2.org\/claims\/ enduserTenantId":"-1234",
"http:\/\/wso2.org\/claims\/ subscriber":"admin",
"http:\/\/wso2.org\/claims\/ tier":"Unlimited",
"http:\/\/wso2.org\/claims\/ applicationid":"1",
"http:\/\/wso2.org\/claims\/ usertype":"APPLICATION",
"exp":1486459587,
"http:\/\/wso2.org\/claims\/ apicontext":"\/jwtapi\/1.0.0"}
4. Since we get the claims values with an escape character, we need to replace the "/" with a blank.
This is the actual value we get : "http:\/\/wso2.org\/claims\/ enduser":"admin@carbon.super",
Replace function : jsonStr=jsonStr.replace("\\", "");
After Replace : "http://wso2.org/claims/ enduser":"admin@carbon.super",
5. Then if we need to perform our acceptation and rejection based on enduser value as we have decided, we should split the enduser value by the below claim. You can use any claim value from the above.
var tempStr = new Array();
tempStr= jsonStr.split('http://wso2. org/claims/enduser\":\"');
6. We have split it in to 2 values. So the rest of the value after the enduser claim which is in tempStr[1], we split again to retrieve only the enduser value which is admin@carbon.super.
Value needs to be split :
admin@carbon.super",
"http://wso2.org/claims/ enduserTenantId":"-1234",
"http://wso2.org/claims/ subscriber":"admin",
"http://wso2.org/claims/tier": "Unlimited",
"http://wso2.org/claims/ usertype":"APPLICATION",
var decoded = new Array();
decoded = tempStr[1].split("\"");
7. To access the enduser value in our synapse level, we need to set the decoded enduser value in to message context as below by setting it as a property. I have set it as username.
setProperty(String key, Object value)
Set a custom (local) property with the given name on the message instance
mc.setProperty("username", decoded[0]);
8. Then use a filter mediator to perform action based on the username. In here, I have logged a message if the username = admin@carbon.super and dropped the request if it is another user. For more information on Filter mediator, please have a look at this [2]
"1.0" encoding="UTF-8" xml version=
<filter source="get-property(' username')" regex="admin@carbon.super">
<then>
<log level="custom">
<property name="accept" value="Accept the message" />
</log>
</then>
<else>
<drop />
</else>
</filter>
9. I have uploaded my custom mediation extension via publisher as given in the below screen. You have to republish the API once you save it, if it is already published.
So my complete mediation extension is as below :
<sequence xmlns="http://ws.apache.org/ns/synapse" name="JWTDec"> <log level="custom"> <property name="X-JWT-Assertion" expression="get-property('transport','X-JWT-Assertion')"/> </log> <property name="authheader" expression="get-property('transport','X-JWT-Assertion')" scope="default" type="STRING" description="get X-JWT-Assertion header"/> <script language="js" description="extract username"> var temp_auth = mc.getProperty('authheader').trim(); var val = new Array(); val= temp_auth.split("\\."); var auth=val[1]; var jsonStr = Packages.java.lang.String(Packages.org.apache.axiom.om.util.Base64.decode(auth), "UTF-8"); jsonStr=jsonStr.replace("\\", ""); var tempStr = new Array(); tempStr= jsonStr.split('http://wso2.org/claims/enduser\":\"'); var decoded = new Array(); decoded = tempStr[1].split("\""); mc.setProperty("username",decoded[0]); </script> <log level="custom"> <property name="username" expression="get-property('username')"/> </log> <filter source="get-property('username')" regex="admin@carbon.super"> <then> <log level="custom"> <property name="accept" value="Accept the message"/> </log> </then> <else> <drop/> </else> </filter> </sequence>
No comments:
Post a Comment