How to decode the encrypted JWE token using the ECDH-ES+A128KW

I am currently on the cloud version of apigee. How to decode the encrypted JWE token encrypted with ECDH-ES+A128KW?

If I configure <Algorithms> <Key>ECDH-ES+A128KW</Key> </Algorithms> on the VerifyJWT policy, I got "Invalid configuration: policy(JWT-VerifyToken) element(Algorithms)." error.

For my case, I just need to read one of the claim attribute to direct to the downstream from apigee. I do not need to encrypt the content.

0 4 4,769
4 REPLIES 4

The following works for me.

<VerifyJWT name="VerifyJWT-ECDH-ES-A128KW">
  <Source>request.formparam.JWT</Source>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <Algorithms>
    <Key>ECDH-ES+A128KW</Key>
  </Algorithms>
  <PrivateKey>
    <Value ref="private.ec_privatekey"/>
  </PrivateKey>
</VerifyJWT>

What that does is, it decrypts the inbound token, using the provided EC key, and verifies that the token is not expired, and is valid. And of course if you want to verify additional claims, you could add elements like Subject, Issuer, and so on., to check those AFTER the decryption happens.

You wrote:

How to decode the encrypted JWE token

I'm glad you asked that question. Straight up: You cannot "decode" an encrypted token. I want to be clear here that Apigee treats "decoding" as different than "decrypting".

  • Decode = split the JWT by dots, and base64-decode the resulting parts. In Apigee, the DecodeJWT policy does this.
  • Decrypt = decrypt the JWT, and implicitly Verify the encryption, using the private key. In Apigee, the VerifyJWT policy does this.

The JSON payload of an encrypted token is encrypted, so you cannot see it after a decode. The only way to see what it is, to get the payload JSON, is to decrypt the payload content, and in order to do that, you need to have the decrypting key. In the case of a JWT using ECDH-ES+A128KW , you will need an EC Private key.

A decode operation will give you the HEADER of an encrypted JWT. The header contains metadata about the JWT, like the key encrypting algorithm, the content encrypting algorithm, and maybe some other stuff. For a JWT that is encrypted with ECDH-ES+A128KW, the header might look like this:

{
  "typ": "JWT",
  "enc": "A256CBC-HS512",
  "alg": "ECDH-ES+A128KW",
  "epk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "oV6ZbodvsQedFbAMziyglQMY5d19yZbWpQGt4FawYgQ",
    "y": "uuRwp4DqMM6SAgmx7H--w3cYNL71ioO8y5Lt-hmMGtg"
  }
}

... but you won't be able to see the payload.

I am not sure if your use of the word "decode" was intentional, so I wanted to clearly differentiate between Decode and Decrypt.

In fact, I need to decrypt the JWE token and read one of the claim attributes in the decrypted JWS (in RSA_PSS_USING_SHA256) token.

I have uploaded the private key to KVM and followed your instruction to create the VerifyJWT. However, I got an invalid token error "Payload of JWE object is not a valid JSON object".

Simply speaking, when I program it in java, I have to do

1. Decrypt the JWE token

2. and then validate the decrypted JWS token with RSA_PSS_USING_SHA256.

In apigee, I want to do step #1 without doing step #2 but able to extract one of the claim attributes in the decrypted JWS token.

Is there any way I could extract the claim attributes in the decrypted token?

Hi Dorian,

We recently did some work on using JWE (lot of learnings along the way). Fair ask on point 1 we extended below repo and reused. If you need help can do a sample and share it but if you want to explore you can do it as it is not that hard.

https://github.com/apigee/iloveapis2015-jwt-jwe-jws/tree/master/jwe/callout

In general if there is a policy which might have been available OOB it would have helped in general use case.

My personal choice using Java callout is more controlled approach..We couldn't use policy approach & went with extending java callout's for JWT/JWS & recently with JWE (for FAPI implementation).

BTW i learnt something around JWE as not much documentation isn't available..Please read & make sure to read below article..

https://community.apigee.com/questions/90371/jwe-direct-key-working-sample.html

Also:

https://docs.apigee.com/api-platform/reference/policies/verify-jwt-policy

Note: By default, the JWT is retrieved from the variable request.header.authorization. In this case, Edge looks for the JWT in the request Authorization header. If you pass the JWT in the Authorization header, you do not need to include the Source element in the policy; however, you must include Bearer in the auth header. For example, you would pass the JWT in the Authorization header like this:

curl -v http://52.200.92.187:9001/doctest-jwt/verify-rs256 -H "Authorization: Bearer <your JWT>"

You can configure to policy to retrieve the JWT from a form or query parameter variable or any other variable. If the variable does not exist or if the policy otherwise can't find the JWT, the policy returns an error.

-Vinay

Dorian

I think maybe what you have is

  • a JWE (not an encrypted JWT)
  • and the payload of the JWE is a JWS.

The builtin policies in Apigee currently do not have the capability to decrypt a JWE .

For that you can use a separate implementation. This repo has an example that decrypts JWE, which is pretty close to what you want for step 1, except that it handles only RSA encryption, not ECDH.

I can look into enhancing that repo to also handle ECDH, but no promises. You could do the work yourself if you are inclined and disposed to do so.