Constructing the JWT Assertion to box

@Dino:

As per https://community.apigee.com/questions/13878/jwt-policy.html creating a new thread as it is getting little tricky to use the existing java code in github.

Ref:

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

Two issues:

1. Issue with "audience" standard property , as per box(https://box-content.readme.io/docs/app-auth)it

expects as string which is valid as per JWT spec.

https://tools.ietf.org/html/rfc7519

Even though we convert it to string when the claim set gets generated with base64encoded url it is converting to array and not as string.

<Property name="audience">https://api.box.com/oauth2/token</Property>

2.Other issue with escape characters "/" with in the audience URI ,even though we replace the string it still shows as https:/\/\api.box.com/\oauth2/\token

If we fix the passing a string & get rid of escape characters we should be able to get the token.

Still trying to figure out but let me know if you can try with box & let us know if it is successful to get the token?

Solved Solved
0 7 1,039
1 ACCEPTED SOLUTION

To create a JWT for use with Box, you can use something like this for the policy config:

<JavaCallout name='JavaCallout-JWT-Create'>
  <DisplayName>JavaCallout-JWT-Create</DisplayName>
  <Properties>
    <Property name="algorithm">RS256</Property>
    <Property name="debug">true</Property>
    <Property name="private-key">{variable-that-contains-private-key-PEM}</Property>
    <Property name="private-key-password">{variable-holding-PEM-password-here}</Property>
    <Property name="subject">urn:75E70AF6-B468-4BCE-B096-88F13D6DB03F</Property>
    <Property name="issuer">api-key-goes-here-78B13CD0-CEFD-4F6A-BB76</Property>
    <Property name="audience">https://api.box.com/oauth2/token</Property>
    <Property name="expiresIn">30</Property> <!-- in seconds -->
    <Property name="claim_box_sub_type">enterprise</Property>
    <Property name="claim_jti">45760806-BAD5-4A01-896A-C5811436C377</Property>


    <!-- other custom claims to embed -->
    <Property name="claim_my_custom_claim1">{context.var.here}</Property>


  </Properties>


  <ClassName>com.apigee.callout.jwt.JwtCreatorCallout</ClassName>
  <ResourceURL>java://jwt-signed-edge-callout.jar</ResourceURL>
</JavaCallout>

View solution in original post

7 REPLIES 7

Hi Vinay! thanks for creating the new thread. It's easier to follow this way.

I don't understand this statement fof yours:

> Even though we convert it to string when the claim set gets generated with base64encoded url it is converting to array and not as string.

Who is "we"? how are you converting it to a string? Can you point to some specific code relevant to this? Is it code in your API proxy that is doing the conversion? Or are you referring to the code in the custom Java policy?

Here's what I know about the audience claim (from the spec that you cited):

> the "aud" value is an array of case- sensitive strings, each containing a StringOrURI value. In the special case when the JWT has one audience, the "aud" value MAY be a single case-sensitive string containing a StringOrURI value.

I *think* the code in the jwt_signed callouts correctly deals with the special case of a single string. Actually there are two callouts, and I am not clear on which one we are discussing here. One callout Generates JWT, and another one Parses JWT. Which one are you referring to?

  • In the case of Generate, the generated JWT has an audience which is a single string. It looks like this:
    {
      "exp": 1458757198,
      "sub": "http://dinochiesa.net",
      "aud": "jwt_signed",
      "iss": "ApigeeEdge-deecee-test-/jwt_signed/create-HS256",
      "shoesize": "9",
      "motto": "Iloveapis",
      "iat": 1458755398
    }
    	

    This seems to be completely valid according to the spec. Do you believe there is a problem here?

  • In the case of Parsing a JWT, the code handles either the array or single-string audience. In fact the nimbus library that is used in the callout presents a List<String> for audience, and I presume (but have not tested) that the nimbus code works properly even in the special case where the aud value is a single string.

I think you are saying that one of the above is not true. That somehow the audience is not handled properly. But I don't understand specifically which case, and what specifically is going wrong.

Can you elaborate? If you are saying that the parse is not being done properly, can you present to me a JWT which causes the error, which I can use for testing? If you are saying that the Generate is not being done properly, please clarify how or why.

> it still shows as https:/\/\api.box.com/\oauth2/\token

this is an artifact of the Trace UI. The actual value is correct. (no backslashes)

Not applicable

@Dino - thanks for the info. This is the jwt-signed-edge-callout code in JwtCreatorCallout.java.

It uses JWTClaimsSet which does not support adding a single AUD claim, and always expects an array. The JWTClaimsSet.Builder class does seem to support this in a different version 4.0 of the nimbus-jose-jwt library, however in the version currently being used 2.21, the Builder class is not available.

I can look at moving to a later version of the nimbus JAR, but...

I still don't understand the problem.

The "always expects an array" is a statement about the Java programming model exposed by Nimbus. That shouldn't affect a user of the custom policy in Edge; from that perspective the Nimbus jar is an implementation detail. When the array (I think it might be a List) is of length 1, then the aud claim gets serialized by Nimbus as a simple string. All this seems to be in compliance with the JWT spec. When the List is of length > 1, then it gets serialized as an array. I think JWT parsers ought to be able to handle either, according to the spec.

I don't understand the problem we are discussing.

Separate thing - are you working with Vinay? Are you two discussing the same situation? Or do you have an independent concern?

@Dino

yes we are working with Vinay on this. Same situation. regards.

Now there are three people asking!? 🙂

To create a JWT for use with Box, you can use something like this for the policy config:

<JavaCallout name='JavaCallout-JWT-Create'>
  <DisplayName>JavaCallout-JWT-Create</DisplayName>
  <Properties>
    <Property name="algorithm">RS256</Property>
    <Property name="debug">true</Property>
    <Property name="private-key">{variable-that-contains-private-key-PEM}</Property>
    <Property name="private-key-password">{variable-holding-PEM-password-here}</Property>
    <Property name="subject">urn:75E70AF6-B468-4BCE-B096-88F13D6DB03F</Property>
    <Property name="issuer">api-key-goes-here-78B13CD0-CEFD-4F6A-BB76</Property>
    <Property name="audience">https://api.box.com/oauth2/token</Property>
    <Property name="expiresIn">30</Property> <!-- in seconds -->
    <Property name="claim_box_sub_type">enterprise</Property>
    <Property name="claim_jti">45760806-BAD5-4A01-896A-C5811436C377</Property>


    <!-- other custom claims to embed -->
    <Property name="claim_my_custom_claim1">{context.var.here}</Property>


  </Properties>


  <ClassName>com.apigee.callout.jwt.JwtCreatorCallout</ClassName>
  <ResourceURL>java://jwt-signed-edge-callout.jar</ResourceURL>
</JavaCallout>