Verify jwt using jwks

Hi, i'm trying to verify a jwt using a jwks and reading the documentation i've found that the verify policy can automatically lookup for the matching kid in the jwks and choose that key. The policy is able to choose the correct jwk but it always fail when try to parse the key. The error description is this:

{"fault":{"faultstring":"Failed to parse key: policy(VerifyJWT)","detail":{"errorcode":"steps.jwt.KeyParsingFailed"}}}

I'm using a service callout to retrive the jwks and my verify jwt policy look like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<VerifyJWT continueOnError="false" enabled="true" name="VerifyJWT">
<DisplayName>VerifyJWT</DisplayName>
<Algorithm>RS256</Algorithm>
<PublicKey>
<JWKS ref="calloutResponse2.content"/>
</PublicKey>
<Source>jwt-token</Source>
</VerifyJWT>

 

 

the jwks that i'am using is:

{"keys":[{
"kty":"RSA",
"n":"-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEArh2Jg62AjdRW8ISAWujT
CQu1eehMxaiCc6LXw8rvtB/+U02LWGzl7KW7TrIc9N6oPfmbOFCHahfA3/eBGD/w
PCQT4E/580NLPw1tsnvFStnksogv6gULBElmEQElpeJEeWUTV8yxkNp10w5qmtaC
0sZOrGvn16/Fq9GOijuAMpNyX+H1Gw1n44ghB4oeQvyL30keYQx1noNnyo6xgtpF
Djf7+WLpIp8q4k1S2r8/IuoW6IbwUSKT3vzZimF4APCCk0RfPz5mlVq3f/ee9CJF
VNsmpnTVs5WrxyH+q/lhcusAaYGm4Hdzeuw0Jc0IM9Bd05qIXuC0nPfZp6yqiHO9
S53iCr9ku1w4QH5WgRGLgveLRmb6s3c5UQWSy7HxSDBIk5s0AS1exKcIxrjpsjdG
O4v5uQp8oCzL8iJ9cqNVORjQpAJCtVfSeOj3yb0iPU+yKJaw7/e7pwruO/3iOWb6
p5usY2SRAkxT4+MhtLLE26Wk7VYw4jDlsSRsXWlotEmRMvNafq+7GtaM0vnb3z5s
pIkZK9dA5f8Cjn8cH6I+7OxO0v7q8rZ0Lw6y8mn8sbDXV31gglHlamPQoH3LQ/cM
4IsUv4CdELD7sZ26skmOGYGiduM/eoHIQIzehuEQEVqByhQapQ8ssFGVXSdBLn+U
+cIdPTcbbdECxUo/pba+evECAwEAAQ==
-----END PUBLIC KEY-----",
"e":"AQAB",
"alg":"RS256",
"kid":"1234"
}]


 

Thank you

Solved Solved
0 4 2,202
1 ACCEPTED SOLUTION

That JWK is not in the correct JWKS format. The error message you saw, (Failed to parse key: policy(VerifyJWT)), indicates that Apigee cannot parse the JWK. And that would be expected.

It seems like you contrived that JWKS. The n string should not have a "BEGIN PUBLIC KEY" in it.

Your IDP, the thing that issues the token, will have a JWKS endpoint if it supports OpenID Connect. You need to find it and USE THAT. The content available at that JWKS endpoint will have a valid format.

If you do not have an IDP, then you can try using this example JWKS and token-generator service. https://jwks-service.appspot.com/. This should be used only for testing.

To use that test service, you can

  1. configure your VerifyJWT policy to reference the JWKS URI, like this

    <VerifyJWT name='VJWT-1'>
      <Algorithm>RS256</Algorithm>
      <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
      <PublicKey>
        <JWKS uri='https://jwks-service.appspot.com/.well-known/jwks.json'/>
      </PublicKey>
      <!-- other elements here as desired -->
    </VerifyJWT>
    
  2. use the web app to generate a signed JWT using an RSA key with RS256

  3. copy/paste that generated JWT, and then pass it in via an http request, to a proxy that contains the verifyJWT policy.

View solution in original post

4 REPLIES 4

That JWK is not in the correct JWKS format. The error message you saw, (Failed to parse key: policy(VerifyJWT)), indicates that Apigee cannot parse the JWK. And that would be expected.

It seems like you contrived that JWKS. The n string should not have a "BEGIN PUBLIC KEY" in it.

Your IDP, the thing that issues the token, will have a JWKS endpoint if it supports OpenID Connect. You need to find it and USE THAT. The content available at that JWKS endpoint will have a valid format.

If you do not have an IDP, then you can try using this example JWKS and token-generator service. https://jwks-service.appspot.com/. This should be used only for testing.

To use that test service, you can

  1. configure your VerifyJWT policy to reference the JWKS URI, like this

    <VerifyJWT name='VJWT-1'>
      <Algorithm>RS256</Algorithm>
      <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
      <PublicKey>
        <JWKS uri='https://jwks-service.appspot.com/.well-known/jwks.json'/>
      </PublicKey>
      <!-- other elements here as desired -->
    </VerifyJWT>
    
  2. use the web app to generate a signed JWT using an RSA key with RS256

  3. copy/paste that generated JWT, and then pass it in via an http request, to a proxy that contains the verifyJWT policy.

Hi @dchiesa1 

Hope you are doing great!!
Actually I want to ask that Can we pass jwks url as dynamic in apigee?

In the future, please create a new post. 

For dynamic URIs, you can use the following:

 

<PublicKey>
    <JWKS uriRef="variable-containing-a-uri-that-returns-a-jwks"/>
</PublicKey>

 

See https://cloud.google.com/apigee/docs/api-platform/reference/policies/verify-jwt-policy#publickeyjwks

Alternatively, you can fetch the contents from the JWKS using a Service Callout, which will store the response contents in a variable.

You then reference THAT variable in the JWT policy via: 

 

<PublicKey>
    <JWKS ref="public.jwks"/>
</PublicKey>

 

The Service Callout target URL can be dynamic, as can the variable you reference in the JWT policy.

More information at https://cloud.google.com/apigee/docs/api-platform/reference/policies/jwt-policies-overview#usingajso...

JWKS isn't valid. sample reference from the spec which will help.

https://datatracker.ietf.org/doc/html/rfc7517#appendix-A