JWT nullable values

Hi team, My customer came to this case:

1. Create JWT (Generate JWT policy):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GenerateJWT async="false" continueOnError="false" enabled="true" name="Generate-JWT-1">
    <DisplayName>Generate JWT-1</DisplayName>
    <Algorithm>HS256</Algorithm>
    <SecretKey>
        <Value ref="private.key"/>
    </SecretKey>
    <Subject>subject-subject</Subject>
    <Issuer>urn://apigee-edge-JWT-policy-test</Issuer>
    <Audience>audience1,audience2</Audience>
    <ExpiresIn>8h</ExpiresIn>
    <AdditionalClaims ref="json_claims"/>
    <OutputVariable>jwt-variable</OutputVariable>
</GenerateJWT> 

2. Pass to <AdditionalClaims ref="json_claims"/> JSON object with nullable value (first level, not nested):

<AssignVariable>
        <Name>json_claims</Name>
        <Value>{
  "sub" : "person@example.com",
  "iss" : "asdasd",
  "denis" : null,
  "non-registered-claim" : {
    "denis2" : null,
    "https://example.com/foobar" : { "p": 42, "q": null }
  }
}</Value>
    </AssignVariable> 

The 'denis' claim will not appear at the JWT at all.

Expected: "denis" : null, However, claims like "denis2" and "q" are appeared as expected, with : null value

If any value passed to "denis", e.g.> "denis" : "val" - it will appear

-D

Solved Solved
0 3 2,232
1 ACCEPTED SOLUTION

Yes, it appears that the GenerateJWT policy discards null values for toplevel claims .

As a workaround, if you need a JWT with null values for claims, then you can use the GenerateJWS policy and "manually" specify the payload. It looks like this:

<GenerateJWS name='gjws-001'>
  <Algorithm>RS256</Algorithm>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <PrivateKey>
    <Value ref="private.key"/>
    <Id ref='private_key_id'/>
  </PrivateKey>
  <Payload ref='json_claims'/>
  <AdditionalHeaders>
     <!-- these are optional -->
    <Claim name='typ' ref='variable_holding_typ'/>
    <Claim name='cty' ref='variable_holding_cty'/>
  </AdditionalHeaders>
  <OutputVariable>variable-name-here</OutputVariable>
</GenerateJWS>

The json_claims should have a JSON string, the result of JSON.stringify(). Or, something like you have in your AssignVariable. In the case of using GenerateJWS, if you want iat, exp or nbf, then you need to specify those claims explicitly in the json_claims variable.

GenerateJWS generates a JWS. a JWT is a special case of JWS, in which the payload is JSON. We can say that not all JWS are signed JWT, but all signed JWT are JWS. If you specify a json payload, you can use GenerateJWS to generate a signed JWT.

View solution in original post

3 REPLIES 3

Yes, it appears that the GenerateJWT policy discards null values for toplevel claims .

As a workaround, if you need a JWT with null values for claims, then you can use the GenerateJWS policy and "manually" specify the payload. It looks like this:

<GenerateJWS name='gjws-001'>
  <Algorithm>RS256</Algorithm>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <PrivateKey>
    <Value ref="private.key"/>
    <Id ref='private_key_id'/>
  </PrivateKey>
  <Payload ref='json_claims'/>
  <AdditionalHeaders>
     <!-- these are optional -->
    <Claim name='typ' ref='variable_holding_typ'/>
    <Claim name='cty' ref='variable_holding_cty'/>
  </AdditionalHeaders>
  <OutputVariable>variable-name-here</OutputVariable>
</GenerateJWS>

The json_claims should have a JSON string, the result of JSON.stringify(). Or, something like you have in your AssignVariable. In the case of using GenerateJWS, if you want iat, exp or nbf, then you need to specify those claims explicitly in the json_claims variable.

GenerateJWS generates a JWS. a JWT is a special case of JWS, in which the payload is JSON. We can say that not all JWS are signed JWT, but all signed JWT are JWS. If you specify a json payload, you can use GenerateJWS to generate a signed JWT.

I've opened ticket and this confirmed, and trasnferred to eng. team

I also will try your workaround, thanks Dino

May be dino's existing java callout would work as you expect.. If you pass claim_json_account as one of the property may be it will work as expected. Tested with a use case & jwt generated has expected claims. Its about the choice..

String jsonClaim = "{\"id\":null,\"verified\":true,\"allocations\":[4,\"seven\",false]}";

jwt-claims.png

https://github.com/apigee/iloveapis2015-jwt-jwe-jws/blob/master/jwt_signed/callout/src/main/java/com...