Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

Decode JWT Policy concerns and question

We have a client sending JWT token in Authorization header of REST call using bearer. Since the JWT is part of bearer, I am not using a source variable as per the documentation, neither I need verify keys if I am using this policy.

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

Here is my default JWT policy

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <DecodeJWT async="false" continueOnError="false" enabled="true" name="Decode-JWT-2"> <DisplayName>Decode JWT-2</DisplayName> </DecodeJWT>

1. Whenever I add this, I get the following error. I get a proper response when I remove this policy.

{
    "fault": {
        "faultstring": "Unable to identify proxy for host: partner and url: /xyz-app/ticker",
        "detail": {
            "errorcode": "messaging.adaptors.http.flow.ApplicationNotFound"
        }
    }
}

2. I understand we can do simple JWT decoding and validation, for instance verifying the audience as below.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<DecodeJWT async="false" continueOnError="false" enabled="true" name="Decode-JWT-1">
    <DisplayName>Decode JWT-1</DisplayName>
    <Audience>https://abc.com/ApigeeWeb</Audience>
</DecodeJWT>

but how do I validate a JWT which has array element? For example, if my JWT has

"group": [
    "group-1",
    "group-2",
    "group-3"
  ]

How can I validate if the incoming JWT request contains group-2?

Thank you,

Himalay

Solved Solved
0 5 1,218
1 ACCEPTED SOLUTION

The first problem: "Unable to identify proxy for host: partner and url: /xyz-app/ticker"

...means there is no API proxy listening at the given hostname and basepath. Check that your proxy is deployed to an environment. Also check that the host+path you are using when invoking the API proxy is the same as the vhost for the environment in which it is deployed, and the basepath configured in your proxy. The error has nothing directly to do with the DecodeJWT policy you are using. The failed request isn't getting that far.


Regarding the second question.

DecodeJWT does not verify a JWT. It simply decodes it. As a side effect, the policy sets variables in the context that hold the content of the decoded (but not verified) JWT header and payload. One of the variables will hold the value of the audience claim , if there is an audience claim. Check the documentation on the DecodeJWT policy for details.

In short, including the <Audience> element into the DecodeJWT policy does nothing. It's also misleading. Don't do that.

You cannot, within the policy itself, check that a custom array claim (like your group example) contains a specific value.

To check that a JWT array claim (like your group example) holds a particular value, you can use a regex match, in a condition that is evaluated AFTER the DecodeJWT policy.

    <Step>
        <Name>Decode-JWT-1</Name>
    </Step>
    <Step>
        <Condition>NOT (jwt.Decode-JWT-1.claim.group ~~ "^\[.*group-2.*\]$")</Condition>
        <Name>RF-MissingGroup</Name>
    </Step>

BUT THIS IS A NO GOOD, TERRIBLE, VERY BAD IDEA.

Depending on the outputs of DecodeJWT for authorization decisions is a bad idea.

The DecodeJWT policy does not verify a JWT.
The DecodeJWT policy does not verify a JWT.
The DecodeJWT policy does not verify a JWT.

All the decode policy does is *decode* the token. It does not verify the signature. The JWT could have any content in it at all. The JWT could have been changed or completely contrived. It could be completely unsigned. By simply trusting the data that is passed in the JWT, without verifying the signature, you are trusting what the unauthenticated client is sending to you. Obviously unacceptable.

You need to use the VerifyJWT policy to verify the signature on the JWT. The VerifyJWT policy also sets variables in the same way I described above for DecodeJWT. After VerifyJWT you can use the same regular expression match (with ~~) to check the value of the VERIFIED group claim.

The correct flow will be something like this:

    <Step>
        <Name>Verify-JWT-1</Name>
    </Step>
    <Step>
        <Condition>NOT (jwt.Verify-JWT-1.claim.group ~~ "^\[.*group-2.*\]$")</Condition>
        <Name>RF-MissingGroup</Name>
    </Step>

And of course the Verify-JWT-1 policy is a VerifyJWT, something like this:

<VerifyJWT name="Verify-JWT-1">
    <Algorithm>RS256</Algorithm>
    <PublicKey>
        <Value ref='publickey'/>
    </PublicKey>
    <Audience>https://abc.com/ApigeeWeb</Audience>
    <Issuer>urn://Issuer</Issuer>
</VerifyJWT>

View solution in original post

5 REPLIES 5
Top Solution Authors