Hi,
I have this JWT:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0LXN1YmplY3QiLCJhdWQiOlsiYXVkaWVuY2UxIiwiYXVkaWVuY2UyIl0sImlzcyI6InVybjpcL1wvYXBpZ2VlLWVkZ2UtSldULXBvbGljeS10ZXN0IiwiZXhwIjoxNTkwNTM3OTA4LCJhY3Rpb25zIjoiYVwvYlwvYVwvYlwvYVwvYyIsImlhdCI6MTU5MDUwOTEwOCwianRpIjoiM2M3NGEyM2QtZTU1ZS00N2I5LTkxZWUtMDUxOGQyY2MwYzFmIn0.nkD2RUr5NNGG3bqO0UMCO33MD_ld91CI0jgTdZhmy1M
This JWT have custom claim called actions:
"actions": "a/b/a/b/a/c"
as you can see, this string have the '/' element.
Once we are decoding this in Apigee (or other tools) - we can see in the final variable, that this claim getting escaped: (payload-json var)
{"sub":"subject-subject","aud":["audience1","audience2"],"iss":"urn:\/\/apigee-edge-JWT-policy-test","exp":1590540403,"actions":"a\/\/b\/\/a\/\/b\/\/a\/\/c","iat":1590511603,"jti":"675646c9-ec88-4fe0-9689-5aef7f75095e"}
and also urn...
My backend can't work with this escaping
Any ideas?
Solved! Go to Solution.
Thanks for that. what I understand is:
I just tested GenerateJWT with your configuration and a variable that holds "a/b/c/d" and I see that the base64-decoded payload looks like this:
{"aud":["audience1","audience2"],"iss":"urn:\/\/apigee-edge-JWT-policy-test","exp":1590643673,"actions":"a\/b\/c\/b","iat":1590614873,"jti":"a264a537-32cd-4fd1-9cda-507f96566297"}
...which is consistent with my understanding of your description.
It's unfortunate, but: Escapes of forward slash are valid though not required in JSON.
A correct processor of JSON must be able to handle backslash-escaped forward slashes. Since the JWT payload is simply JSON, While you might look at the behavior of Apigee GenerateJWT here and say "I don't want the escapes" , it is correct and valid. The way to avoid the problem is: the backend needs to handle the escaped JSON properly.
One *possible* workaround is to use the GenerateJWS policy. The GenerateJWS policy signs a payload, similar to the way the GenerateJWT signs a payload. But, the payload in a JWS can be "anything", any stream of bytes. The GenerateJWS policy doesn't assume you want a JSON payload and doesn't quietly insert backslash-escapes for forward-slashes if the payload happens to be JSON.
The policy configuration would look like this:
<GenerateJWS name='GenerateJWS-1'> <Algorithm>HS256</Algorithm> <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables> <SecretKey> <Value ref='private.secretkey'/> <Id>cb24a396-4414-4793-b4ce-90333b694bff</Id> </SecretKey> <Payload ref='jws-payload'/> <AdditionalHeaders> <Claim name='typ'>JWT</Claim> </AdditionalHeaders> <OutputVariable>output-jwt</OutputVariable> </GenerateJWS>
And before that, you would need to set into the variable "jws-payload", the exact JSON you want to sign. You could use something like this:
<AssignMessage name='AM-Payload'> <AssignVariable> <Name>jws-payload</Name> <Value>{"aud":["audience1","audience2"],"iss":"urn://apigee-edge-JWT-policy-test","exp":1590643673,"actions":"a/b/c/b","iat":1590614873,"jti":"a264a537-32cd-4fd1-9cda-507f96566297"}</Value> </AssignVariable> </AssignMessage>
Be aware: the iat and exp claims are fixed in this example, and that's probably not what you want. So a better method may be to use a JS step to create the payload and initialize the iat/exp claims as you prefer. Maybe like this:
<Javascript name='JS-SetPayload' > <Source> var payload = { "aud":["audience1","audience2"], "iss":"urn://apigee-edge-JWT-policy-test", "actions":"a/b/c/b" }; var lifetimeInSeconds = 600; var now = new Date(); now = Math.round(now.valueOf()/1000); payload.iat = now payload.exp = now + lifetimeInSeconds; context.setVariable('jws-payload',JSON.stringify(payload)); </Source> </Javascript>