How to verify Nested JWT token

Hi ,

We are using apigee Hybrid . Have to implement JWT token verification in apigee . Please suggest correct approach to achieve .

JWT token is nested token and inner token is encrypted one . I have received public certificate in pem format and  private certificate in .p12 format . 

Here What I am doing for sample implementation . 

1- Created assign message policy and hard code public key which in PEM format to a variable called private.key

2 - Created JWT verify policy 

      Specified algorithm - ES512

      Specified PublicKey - Referencing to private.key 

This policy verifying the token and populating related flow variables .

Inner token is part of the payload(jwe:innertoken) of outer token . 

This token in encrypted. Could any one please give insight how to decrypt this token using the private key which is in .p12 format .  

 

 

Best Regards,

Patty

Solved Solved
0 12 1,027
2 ACCEPTED SOLUTIONS


Further little more help..looks like you may be using incorrect format of private key PEM format looking at your earlier post.
Please do below.
1. Remove the Bag Attributes from the key and use below format in kvm (or may be for simplicity use AssignMessage policy with a variable - private.pvtkey prior to VerifyJWT policy )

 

-----BEGIN PRIVATE KEY-----
<<encoded string>>
-----END PRIVATE KEY-----

 


Good read -> https://docs.apigee.com/how-to-guides/converting-certificates-to-supported-format
2. Now use below policy as stated earlier by dino referencing private key variable - private.pvtkey

 

<VerifyJWT name='VJWT-1'>
  
<Algorithms>

    <Key>ECDH-ES+A256KW</Key>
  
</Algorithms>
  
<PrivateKey>

    <Value ref=“private.pvtkey”/>
  
</PrivateKey>
  <Source>variable-containing-encrypted-jwt</Source>
 ...
</VerifyJWT>

 



Hope this helps.

View solution in original post

yes! Your private key should be of this form: 

-----BEGIN PRIVATE KEY-----
<<base64-encoded string>>
-----END PRIVATE KEY-----

 

View solution in original post

12 REPLIES 12

Have to implement JWT token verification in apigee . Please suggest correct approach to achieve .JWT token is nested token and inner token is encrypted one .

You didn't specify it, but I will guess that the "outer" token is signed. If that's not the case, then the rest of this answer is irrelevant.

The VerifyJWT policy that is builtin to Apigee will verify the signature on a signed JWT. If you have a token that uses the ES512 algorithm for signing, then you need to specify a public key corresponding to that algorithm, to the VerifyJWT policy. You can "hard code" the public key, or retrieve it "dynamically" from a JWKS endpoint. This is all in the documentation for VerifyJWT.  Look for information on the PublicKey element. If you hard-code the key into the policy or into a variable with AssignMessage, it should probably be in PEM format. But you can also use a JWK format. Search for examples in the policy documentation if you don't know what this means.

Once you verify the signed JWT, all of the values of the JWT payload will be available in context variables in the Apigee message context. Supposing the "inner JWT" is stored in the field named "field1", then ... there will be a context variable named jwt.POLICYNAME.decoded.claim.field1 .

You can then use THAT as the source for the second VerifyJWT policy.

The VerifyJWT policy handles encrypted JWT as well as signed JWT. To verify an encrypted JWT, you must specify in the configuration a private key, as well as the Key-encrypting-algorithm. Check the documentation for the policy for more on this. Set the Source as the context variable referring to the field that contains the "inner JWT".

But if your private key is in .p12 format, then you have a challenge. I don't know of a policy or custom callout available for Apigee that can read a .p12-formatted private key and do anything with it. The Apigee JWT policies read .PEM format. If you need to use .p12 then you'd need to build your own solution to convert from .p12 to PEM, before using the 2nd VerifyJWT. Maybe a custom Java callout or a python callout or similar.

Also - some people have previously asked for something similar, but the inner thing was not a JWT. It was a JWE, which is slightly different. The built-in policies in Apigee do not decrypt arbitrary JWE. If you have that scenario , then the builtin policies currently available in Apigee will not satisfy.  You will need an external callout for that second step, the decryption. There is a Java callout here that will do the work, but ... it is limited in that it supports only the RSA-based encryption algorithms. Check the readme there for details. I don't currently have a solution for you if you need to decrypt a JWE that uses a non-RSA algorithm.

Hi Dino ,

Thank you for detail explanation this really helped in understanding . Yes we do have same inner token is JWE . Specified attribute in inner token header are - 

"alg": "ECDH-ES+A256KW",
"enc": "A256CBC-HS512" . 

 

Best Regards,

Patty

Good Question.
What issue are you facing? Provide little more error details..
Check with the system which generated the nested JWT - https://datatracker.ietf.org/doc/html/draft-ietf-oauth-json-web-token#appendix-A.2 (this is very common use case  with nested jwt's in open banking- not exactly though ) & check the process of validation outside the apigee layer to understand  signing/encryption process.
Once you get the concept it will be easy to follow thru & implement in apigee. It's about chaining with in the apigee layer validating outer JWT & reading the values of innner jwt & passing it to next verification with proper alg/enc values..


Can you drop outer/inner JWT into https://jwt.io/ or https://dinochiesa.github.io/jwt/ & validate/review claims ( you may not see if it is encrypted unless you provide pvt key.
 
 

Hi Dino ,

I came across one old community post . But this was working in OPDK not in Hybrid .

Does APIGEE supports JWE and Encryption? - Google Cloud Community

 

Best Regards,

Dwiti

The support I described there for encrypted JWT is available in OPDK, Edge as well as X & hybrid.

But, please note - it applies to Encrypted JWT, which are a particular kind of JWE.

If the distinction is not clear to you, then you'll want to double-check what you have inside the signed JWT.

I'll try to summarize the difference here.

There is a "family" of IETF specifications called JSON Object Signing and Encryption, under the acronym "JOSE".

JOSE includes these specs:

Specification Quick summary Apigee support?
RFC 7515 - JWS JSON Web Signature
Describes how to use JSON to encode a signature of *any* data stream.
Built-in policies
RFC 7516 - JWE JSON Web Encryption
Describes how to use JSON to encrypt and wrap any data stream. (XML or PNG or whatever)
via a Java callout. Support only for RSA-based encryption algorithms.
RFC 7519 - JWT JSON Web Token
Describes how to use either JWS or JWE to sign or encrypt a JSON payload, and also prescribes the semantics of some "well known" claims or properties within that JSON payload, like iss for "issuer" or "issuing party", "aud" for "audience", "sub" for Subject, "exp" for expiry, and so on.
Built-in policies. Works for either signed or encrypted tokens. Supports all the encryption algorithms in RFC 7518.
RFC 7518 - JWA JSON Web Algorithms
Specifies algorithms for signing or encrypting.
Built in support for all of these, via the JWS and JWT policies.

The "JSON" in the name does not imply that the signing or encrypting can be done only on JSON objects. Instead, it implies that the JSON is used to encode the signature. For example you could use JWS to sign a JSON, or a PDF, or a .PNG, or even an XML document. The result is "wrapped in" a JSON wrapper that encodes the signed thing (maybe the XML document) as well as a JSON header that describes how the signature was computed, and the signature bytestream itself. Similarly you can use JWE to encrypt anything, any document or bytestream. One option is to encrypt a JSON payload. The result of that operation we would call an encrypted JWT. Whether using signing or encryption, only if the signed or encrypted payload itself is a JSON object, can we call the result a JWT.

So you see, Apigee has builtin support for "encrypted JWT", which is to say, for JWT that are encrypted according to the JWE spec. Another way to say it is, Apigee has support for JWE, only if the encrypted thing is a JSON object. But Apigee does not have builtin support for JWE in general. For that you need to use the external callout, which as I have said, is limited in that it supports only RSA-based crypto algorithms.

I hope this is all clear.

You gave me the algorithms that are used on the inner thing - which you have called a JWE. And you've also called it a token.

Yes we do have same inner token is JWE

The algorithms you cited are valid algorithms for the JWE, according to RFC 7516. But I'm still not clear on whether the encrypted thing is a JSON or not. If it is a JSON payload, then Apigee supports it. If it is not a JSON payload, then Apigee does not have support for that thing.

I cannot tell, from the information you've given here, what that JWE is. Is it an encrypted JWT, or a general JWE? You need to find out.

Hi Dino ,

Encrypted thing is a JSON . Could you please help me out how to verify / decrypt using OOTB policy . 

 

Below are example header of JWE - 

 

{
"alg": "ECDH-ES+A256KW",
"enc": "A256CBC-HS512",
"kid": "1802",
"epk": {
"kty": "EC",
"x": "AAAAA",
"y": "DDDDDD",
"crv": "P-521"
}
}

Private Key is - .p12

 

Example after converting to PEM

 

Bag Attributes
localKeyID: 12 CC A2 CD 52 07 B5 48 67 24 17 C6 87 53 FB C5 D0 04 B1 6E
friendlyName: oauth gw key
Key Attributes: <No Attributes>
-----BEGIN PRIVATE KEY-----
Removed the encoded string
-----END PRIVATE KEY-----

Best Regards,

Dwiti

Just use the policy. You need to specify in the VerifyJWT configuration, at a minimum,

  • the key encryption algorithm
  • the private key.
  • the source (variable containing eJWT)

Something like this 

<VerifyJWT name=“VJWT-1”>
  <Algorithms>
    <Key>ECDH-ES+A256KW</Key>
  </Algorithms>
  <PrivateKey>
    <Value ref=“private.private-key-PEM”/>
  </PrivateKey>
  <Source>variable-containing-encrypted-jwt</Source>
  …

 

check the documentation for more details. 


Further little more help..looks like you may be using incorrect format of private key PEM format looking at your earlier post.
Please do below.
1. Remove the Bag Attributes from the key and use below format in kvm (or may be for simplicity use AssignMessage policy with a variable - private.pvtkey prior to VerifyJWT policy )

 

-----BEGIN PRIVATE KEY-----
<<encoded string>>
-----END PRIVATE KEY-----

 


Good read -> https://docs.apigee.com/how-to-guides/converting-certificates-to-supported-format
2. Now use below policy as stated earlier by dino referencing private key variable - private.pvtkey

 

<VerifyJWT name='VJWT-1'>
  
<Algorithms>

    <Key>ECDH-ES+A256KW</Key>
  
</Algorithms>
  
<PrivateKey>

    <Value ref=“private.pvtkey”/>
  
</PrivateKey>
  <Source>variable-containing-encrypted-jwt</Source>
 ...
</VerifyJWT>

 



Hope this helps.

yes! Your private key should be of this form: 

-----BEGIN PRIVATE KEY-----
<<base64-encoded string>>
-----END PRIVATE KEY-----

 

Thank you it worked . Delayed in replying .Thank you for the help .

I appreciate the confirmation, thank you!

Thanks