Hi @dchiesa1
Our enterprise is using Apigee X , and in order to validate an IDP minted token which is generated independent of Apigee, we are using the Verify JWT Policy. The policy is currently configured as below, where we are passing the JWKS url within the Public Key element. But we have been receiving the following error below. The value for uriref is fetched from a previous step in Assign Message Policy:
Error Response:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage continueOnError="false" enabled="true" name="AM-AssignJWKS">
<DisplayName>AM-AssignJWKS</DisplayName>
<Properties/>
<AssignVariable>
<Name>kid_header</Name>
<Ref>jwt.JWT-DecodeJWT-KID.header.kid</Ref>
</AssignVariable>
<AssignVariable>
<Name>jwksurl</Name>
<Value>https://test.auth.highmark.com/oauth2/rest/security --header X-OAUTH-IDENTITY-DOMAIN-NAME: <value of kid>/Value>
</AssignVariable>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>
Verify JWT
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<VerifyJWT continueOnError="false" enabled="true" name="JWT-VerifyJWKS">
<DisplayName>JWT-VerifyJWKS</DisplayName>
<Algorithm>RS256</Algorithm>
<!-- <Source>request.header.authorization</Source> -->
<PublicKey>
<JWKS uriRef="jwksurl"/>
</PublicKey>
</VerifyJWT>
I have tried to hardcode value of kid in Assign Message policy, I have also tried to assign the value of variable that is having the value of the kid in the Assign Message policy but even that has not worked.
I am sharing the JWT token (expired) :
eyJraWQiOiJhcGlnZWUtZGVtby1hcGltIiwieDV0IjoicUd5V1QxUVQteW9zcHpmZzN4M2htOFkxcDNZIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL29hdXRocWEuaG1ocy5jb20iLCJhdWQiOlsiaHR0cHM6Ly9jZHNzb3Rlc3QuaGlnaG1hcmsuY29tOjQ0My9vYXV0aDIiLCJyZXNvdXJjZSIsImFiMCJdLCJleHAiOjE3MTExMDg4MjgsImp0aSI6IjhBZ1FjaEptLVlaTU5TNldhVGRHanciLCJpYXQiOjE3MTExMDUyMjgsInN1YiI6IjQyMzQ0NDctMDMwNC01NDM3LWE2NzQyNDQ0ZTRhNTM1NjU0MmY0ZDQ0NzU2NTY3M2QzZCIsImNsaWVudCI6IjQyMzQ0NDctMDMwNC01NDM3LWE2NzQyNDQ0ZTRhNTM1NjU0MmY0ZDQ0NzU2NTY3M2QzZCIsInNjb3BlIjpbInJlc291cmNlLlJFQUQiXSwiZG9tYWluIjoiYXBpZ2VlLWRlbW8tYXBpbSIsInVpZCI6IiIsImhta1Rva2VuVHlwZSI6IkNsaWVudElEIiwibWFpbCI6IiIsImdpdmVuTmFtZSI6IiIsInNlc3Npb25JZCI6IiIsInNuIjoiIiwiaXNtZW1iZXJvZiI6IiIsInBybiI6IjQyMzQ0NDctMDMwNC01NDM3LWE2NzQyNDQ0ZTRhNTM1NjU0MmY0ZDQ0NzU2NTY3M2QzZCIsInJlc1NydkF0dHIiOiJSRVNPVVJDRUNPTlNUIiwiaG1rVG9rZW5WZXJzaW9uIjoidjQifQ.nJIi95radCKvclvam_V-wJMkePsF9emoMhGBqj-DI4z-8R6toRqGdTESTWKnUu3lvHXZzt1z3BNaSs9cKGog7_loNYKixwPTqcoBK4VjPhL7SsV8_H5YkrOqfBAWsfsOG3yfsrMD4f3swTukRR6UDv9Gq2XTdULe5y8CK56FseNBy-iILqYr4gf8QW1z7KRyigX-mRCgERR1H0TnjnlkCp6gm-2U18ioxyv4t22iB6NUdCocDd9ayEL2JF_dbpg-qJaQnYgsaWe5Iof4tIM175AjnopFsTpCpWujeeCmuPud_xrXALX3okrlfvstVuM5Uym5XPfi3VCsla0-46IiJA
Request your inputs as what I could be missing or done wrong.
Thanks,
Debjit
Solved! Go to Solution.
Hi Debjit
I am unclear on how the VerifyJWT Policy can use the proxy from Step 1. The policy has options to pass a static uri or an uriRef, but am unclear on how the policy can leverage this proxy.
If I understand what you've done, you have a proxy that accepts a request like
https://test.auth.highmark.com/jwks-getter?domain=apigee-demo-apim
That's a static URL. You can just use that directly in your VerifyJWT policy.
<VerifyJWT continueOnError="false" enabled="true" name="JWT-VerifyJWKS">
<DisplayName>JWT-VerifyJWKS</DisplayName>
<Algorithm>RS256</Algorithm>
<!-- <Source>request.header.authorization</Source> -->
<PublicKey>
<JWKS uri="https://test.auth.highmark.com/jwks-getter?domain=apigee-demo-apim"/>
</PublicKey>
</VerifyJWT>
If you are thinking that you need to support. multiple different oauth domains with the same policy, that means you need to have a dynamic (determined at runtime) uri. In that case you can set a variable, and use uriRef. Set the variable in a policy like
<AssignMessage name='AM-OAuth-JWKS-URI'>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
<AssignVariable>
<Name>oauth_domain_fulluri</Name>
<Template>https://test.auth.highmark.com/jwks-getter?domain={desired_oauth_domain}</Template>
</AssignVariable>
</AssignMessage>
And then the VerifyJWT would be like this;
<VerifyJWT continueOnError="false" enabled="true" name="JWT-VerifyJWKS">
<DisplayName>JWT-VerifyJWKS</DisplayName>
<Algorithm>RS256</Algorithm>
<!-- <Source>request.header.authorization</Source> -->
<PublicKey>
<JWKS uriRef="oauth_domain_fulluri"/>
</PublicKey>
</VerifyJWT>
Also, let me clarify what I said earlier
Embed the Identity domain name as a path segment, rather than a header.
I was suggesting a Path segment, not a query param. So the inbound URL would look like
https://test.auth.highmark.com/oauth2/apigee-demo-apim/.well-known/jwks
And in the jwks wrapper proxy, you would use ExtractVariables to extract the path segment. Like this:
<ExtractVariables name='EV-OAuth-Domain'>
<Source>request</Source>
<VariablePrefix>extracted</VariablePrefix>
<URIPath>
<!-- put the extracted value into extracted.oauth_domain -->
<!-- NB: The Pattern is matched against pathsuffix (what comes AFTER the basepath) -->
<Pattern ignoreCase='false'>/{oauth_domain}/.well-known/jwks</Pattern>
</URIPath>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</ExtractVariables>
And then you have a variable extracted.oauth_domain
, holding the value that you could set into the required header, X-OAUTH-IDENTITY-DOMAIN-NAME
, with an AssignMessage.
THIS WILL WORK. Your query param approach will work, too, though it feels slightly less elegant to me.
But if I were the IDP architect on this system, I would want to avoid the wrapper proxy entirely. Ideally, the JWKS endpoint should not require that header. The JWKS should "natively" extract the domain from a URL path. Wrapping an Apigee proxy around that endpoint as a wrapper, helps, but the ideal solution would be to modify that JWKS endpoint at the source. I understand that might not be quickly feasible!
Hi Dino,
Thank you for sharing the steps in detail, I will keep you posted how it goes. I am sorry but the decisions to update the JWKS URLs is with the IDP team, I will keep you posted about any updates on this front also.
Regards,
Debjit
I just read about this in Assign Message Policy - AssingVariable - Templates
Does that mean in Assign Message policy we can proxy another API which has as hostname as https://api-{env}.highmark.com
If yes will that be applicable to solution you have suggested and help. Could you please share any samples if available that helps to call proxy from the Assign Message if its possible.