using VerifyJWT to verify that an array claim contains a specific value

I have a JWT with custom claims that looks like this -

 

{
  "iss": "https://example.com/",
  "sub": "auth0|12345",
  "aud": [
    "auth.example.com"
  ],
  "iat": 1646403704,
  "exp": 1646490104,
  "azp": "dfslfjsdfjdsofdsfsd",
  "scope": "openid profile email offline_access",
  "permissions": [
    "download:rates",
    "download:invoices"
  ]
}

 

In the Verify JWT Token policy, I want to verify that a request header matches one of the permissions listed in the permissions claim array object.

I have the following in the Verify JWT policy and it's not working -

 

<AdditionalClaims>
<Claim name="permissions" type="string" array="true" ref="request.header.permission"/>
</AdditionalClaims>

 

I'm seeing an error in this policy though the permissions are decoded correctly and showing as context variables -

jwt.JWT-VerifyAccessToken.claim.permissions = [download:invoices, download:rates]

jwt.JWT-VerifyAccessToken.decoded.claim.permissions = ["download:invoices","download:rates"]

This is the error

{"fault":{"faultstring":"Invalid Claim: policy(JWT-VerifyAccessToken) claim(permissions)","detail":{"errorcode":"steps.jwt.InvalidClaim"}}}
Solved Solved
0 2 1,428
1 ACCEPTED SOLUTION

I want to verify that a request header matches one of the permissions listed in the permissions claim array object.
... and it's not working -

Yes, the VerifyJWT policy today does not have the ability to verify that an array claim contains a specific value. It is possible today to configure VerifyJWT to check that an array claim exactly matches a value. But there is no way to perform an "array contains" check within the policy. This is the subject of a feature request, ref: b/169068726. But it has not yet been implemented.

The way to work around this limitation today is to perform the check outside of the VerifyJWT policy. A good option is a JavaScript policy . The flow would look something like this:

 

<Step>
  <Name>VerifyJWT-1</Name>
</Step>
<Step>
  <Name>JS-Check-Permissions</Name>
</Step>

 

The JS logic would look like this:

 

// get permissions in string form
var permissions = context.getVariable('jwt.VerifyJWT-1.decoded.claim.permissions');
// parse the JSON array
permissions = JSON.parse(permissions);

var requestedPermission = context.getVariable('request.header.permission');

if (permissions.indexOf(requestedPermission) < 0) {
  throw new Error('permission denied');
}

 

And if the required permission does not exist in the claim, then the proxy will return a fault:

 

{
  "fault": {
    "faultstring": "Execution of JS-Check-Permissions failed with error: Exception thrown from Javascript &colon; Error: permission denied (JS_Check_Permissions#10)",
    "detail": {
      "errorcode": "steps.javascript.ScriptExecutionFailed"
    }
  }
}

 

View solution in original post

2 REPLIES 2

I want to verify that a request header matches one of the permissions listed in the permissions claim array object.
... and it's not working -

Yes, the VerifyJWT policy today does not have the ability to verify that an array claim contains a specific value. It is possible today to configure VerifyJWT to check that an array claim exactly matches a value. But there is no way to perform an "array contains" check within the policy. This is the subject of a feature request, ref: b/169068726. But it has not yet been implemented.

The way to work around this limitation today is to perform the check outside of the VerifyJWT policy. A good option is a JavaScript policy . The flow would look something like this:

 

<Step>
  <Name>VerifyJWT-1</Name>
</Step>
<Step>
  <Name>JS-Check-Permissions</Name>
</Step>

 

The JS logic would look like this:

 

// get permissions in string form
var permissions = context.getVariable('jwt.VerifyJWT-1.decoded.claim.permissions');
// parse the JSON array
permissions = JSON.parse(permissions);

var requestedPermission = context.getVariable('request.header.permission');

if (permissions.indexOf(requestedPermission) < 0) {
  throw new Error('permission denied');
}

 

And if the required permission does not exist in the claim, then the proxy will return a fault:

 

{
  "fault": {
    "faultstring": "Execution of JS-Check-Permissions failed with error: Exception thrown from Javascript &colon; Error: permission denied (JS_Check_Permissions#10)",
    "detail": {
      "errorcode": "steps.javascript.ScriptExecutionFailed"
    }
  }
}

 

Thank you @dchiesa1 . That works for now.

Once the requested feature is available, it would be good go get everything we need from the Verify JWT policy itself.