apigee generate token exp and iat claims time format (generate token)

to jwt token policy : 

 

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GenerateJWT async="true" continueOnError="false" enabled="true" name="GJ-Generate-carrefour-token">
<DisplayName>GJ-Generate-carrefour-token</DisplayName>
<Algorithm>RS256</Algorithm>
<PrivateKey>
<Value ref="private.private-key-midfid"/>
<Password ref="private.private-key-password-midfid"/>
</PrivateKey>

 <ExpiresIn>8h</ExpiresIn>


<AdditionalHeaders>
</AdditionalHeaders>
<OutputVariable>jwt-c4</OutputVariable>
</GenerateJWT>

 

the expires In claim generates a date time format like This in the Token:

1665496447 

and the backend i Am calling requests  a date in This format: (in ms i think)

1665494999893

how can i get the same format ?

Solved Solved
0 11 814
1 ACCEPTED SOLUTION

is it possible to make work your solution with a JWT policy generation?

I'm sorry if I was not clear earlier. Let me try to clarify.  There is no way to use specifically the GenerateJWT policy to generate a TOKEN (= JWT) with a exp claim that is a milliseconds quantity. This would violate the JWT specification. As APIEvangelist pointed out in a different reply here, the spec requires that exp and iat be in SECONDS. The GenerateJWT policy conforms to that requirement. That specific policy always produces a compliant JWT, and cannot and will not produce an output that expresses those quantities in milliseconds. You cannot do what you describe with the GenerateJWT policy. I hope this is now clear.

There is a similar policy - it is called GenerateJWS.  The GenerateJWS policy generates a signed document according to the JWS spec.

It's a little confusing, all the JWS, JWT, JWE stuff. But, briefly: "JWT" refers JSON Web TOKEN", while JWS refers to JSON Web SIGNATURE. Tokens may be signed or encrypted. When most people say "JWT" they mean "signed JWT". All signed JWT are, by definition, JWS. But not all JWS are JWT.  It is possible to use the GenerateJWS policy to generate a JWT, if you format the payload to be JSON, and use claims that comply with the RFC7519 specification.  Is this helping?

The "solution" I showed above uses GenerateJWS, but it does not generate a JWT. The output will NOT be a JWT, not a compliant one anyway, because of the issue I described above: the JWT specification says that exp and iat must be in SECONDS, not MILLISECONDS. But the output of my example forces the exp and iat claims to be in MILLISECONDS. Therefore,  the output from the specific GenerateJWS example I offered will look like a JWT, but will not be a JWT, by definition. Your upstream system seems to accept that kind of thing - something that looks like a JWT, but is not. So maybe the approach I showed is just what you need.

 

View solution in original post

11 REPLIES 11

You cannot do that. 
the GenerateJWT policy generates a JWT. The exp and iat claims are defined by the standard to be “seconds since epoch”. You cannot configure the policy to behave in the way you describe. It would be insecure for it to do so. 
If your backend system does require the format you describe, I suggest fixing that backend system. It’s insecure! 

First of all Thanks for your response,

Yes my question was about generate token policy

And believe me I'm not a hacker, I'm simply an apigee developer with one of
your clients for this product.

I understand your doubts about my profile but the story is that it's a
partner backend API that we are calling, so i don't have a hand to there
code I must do with what we have, and what we have is payload token with
exp claim in ms.


Conclusion : there is no way to change date format with this policy?

Regards,
AZE

there is no way to change date format with this policy?

Yes and No.

YES, There is no way to use specifically the GenerateJWT policy to generate a TOKEN (= JWT) with a exp claim that expresses milliseconds.

But you may be able to do it with a different policy. There is a way to use the GenerateJWS policy to sign a JSON payload with an exp claim that expresses milliseconds.

The GenerateJWS would look something like this:

 

<GenerateJWS name='GenerateJWS-RSA'>
  <Algorithm>RS256</Algorithm>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <PrivateKey>
    <Value ref="private.rsa-private-key"/>
    <Id ref='rsa-key-id'/>
  </PrivateKey>
  <Payload ref="my-jws-payload"/>
  <AdditionalHeaders>
    <Claim name='typ'>JWT</Claim>
  </AdditionalHeaders>
  <OutputVariable>output-jws-which-looks-like-a-jwt-but-is-not-a-jwt</OutputVariable>
</GenerateJWS>

 

And the my-jws-payload can hold any JSON string. You can assign it with a JS policy (use JSON.stringify()). or with AssignMessage.

 

<AssignMessage name='AM-Contrived-Payload'>
  <AssignVariable>
    <Name>my-jws-payload</Name>
    <Template>{
    "note" : "this is not a JWT, because the iat and exp claims are in milliseconds",
    "iss" : "whatever-you-like",
    "iat" : {system.timestamp},
    "exp" : {computed-expiry}
}</Template>
  </AssignVariable>

</AssignMessage>

 

To compute the expiry as something like "10 minutes in the future" you'd need to resort to JavaScript to do the arithmetic.

I have attached a working example.

thank you for your response,
im trying your solution but im using a JWT (generation)policy not JWS(generation) and im getting a 500  with  the same logic of your solution.
is it possible to make work your solution with a JWT policy generation?

is it possible to make work your solution with a JWT policy generation?

I'm sorry if I was not clear earlier. Let me try to clarify.  There is no way to use specifically the GenerateJWT policy to generate a TOKEN (= JWT) with a exp claim that is a milliseconds quantity. This would violate the JWT specification. As APIEvangelist pointed out in a different reply here, the spec requires that exp and iat be in SECONDS. The GenerateJWT policy conforms to that requirement. That specific policy always produces a compliant JWT, and cannot and will not produce an output that expresses those quantities in milliseconds. You cannot do what you describe with the GenerateJWT policy. I hope this is now clear.

There is a similar policy - it is called GenerateJWS.  The GenerateJWS policy generates a signed document according to the JWS spec.

It's a little confusing, all the JWS, JWT, JWE stuff. But, briefly: "JWT" refers JSON Web TOKEN", while JWS refers to JSON Web SIGNATURE. Tokens may be signed or encrypted. When most people say "JWT" they mean "signed JWT". All signed JWT are, by definition, JWS. But not all JWS are JWT.  It is possible to use the GenerateJWS policy to generate a JWT, if you format the payload to be JSON, and use claims that comply with the RFC7519 specification.  Is this helping?

The "solution" I showed above uses GenerateJWS, but it does not generate a JWT. The output will NOT be a JWT, not a compliant one anyway, because of the issue I described above: the JWT specification says that exp and iat must be in SECONDS, not MILLISECONDS. But the output of my example forces the exp and iat claims to be in MILLISECONDS. Therefore,  the output from the specific GenerateJWS example I offered will look like a JWT, but will not be a JWT, by definition. Your upstream system seems to accept that kind of thing - something that looks like a JWT, but is not. So maybe the approach I showed is just what you need.

 

Thank you it's  way better clear now .

Rebounding again @dchiesa1  about the difference between jws policy and jwt policy, actually its working like that with the jws policy but does it make the call vulnerable? Is it not secure? The token generated with jws is signed with an RSA private key and password , but I would like to know what do you think about this flow.

I think the security of the signed payload (the JWS thing that looks like a JWT) is solid.  Probably it will be just fine. 

The one problem is will the milliseconds vs seconds values.  The header of your signed output contains a claim, typ=JWT.  And that tells receivers the payload should be interpreted as a JWT payload, which means exp and iat are in seconds. 

What happens if a receiver looks at the exp claim and "does the right thing" for interpreting JWT claims?  It will assume that he JWT expires in ....the year 2300.  I don't know, I didn't do the arithmetic.  But the point is it will be very far in the future.   Practically speaking, there is no expiry.  And that means a receiver who is not careful will accept the JWT after it "should have" expired. This could be the result of what is known as a replay attack. 

A defensive receiver would also look at the iat claim, and if it is in the future, especially the far future, a defensively-designed receiver should and would reject that JWT.  But not all receivers validate on the iat claim, and in fact the JWT spec does not explicitly state that the iat claim should be used to evaluate validity. So a receiver that is not carefully designed may simply evaluate the exp claim and be satisfied. 

You can say, "well, our receiver is already known to us, and it needs milliseconds.  We will never send this JWS to any other receiver. Therefore there will never be a problem." That might be true, but there is a possibility in the future that a new maintenance team will come along and will not be aware of all these special arrangements and then you're in trouble. Or someone will see the GenerateJWS policy in your proxy and re-use it in a fresh system that uses a different receiver, and then again you have a problem. 

Suppose you say "Well let's just do it this way for now, and later, in three months or so, we'll fix the receiver so that it does not require milliseconds in the exp quantity."  Fine.  What happens if some party stores a JWS that you issue this way, and then after the receiver gets fixed, that malicious party replays the "old" JWS to the "fixed" receiver. Now the receiver will look for exp to be in seconds, and may treat the old JWS as non-expired. Replay attack.

The reason standards work is because everyone conforms.  If you claim "typ=JWT" in the header and then explicitly put something that is not standard in the payload, then, I would say, you are "asking for trouble."  

In summary, the security of the signed output is not in question. The way it is being employed will work for you today.  There is the potential in the future for confusion or problems. 

The real fix is to correct the system that "insists" on exp and iat being expressed in milliseconds. That system is broken, clearly. It's a security bug that it behaves that way, and I would treat it as a P1 bug in my company.  It needs to be corrected.  It's easy for me to say, because I don't know the deadlines and constraints you are operating under, but I will say it anyway: I would not allow such a system in my enterprise if I were chief system architect. It would be triaged and fixed at the highest priority. 

Maybe you should explicitly NOT set the typ=JWT in the header - maybe select a new custom typ, something else, anything else. Like "non-compliant-JWT".   Something that indicates to readers "this is not really a compliant JWT".  That might make it marginally safer for future readers and maintainers. 

This is all just my opinion.  

thank you again, its so clear, i will try to forward all this infos to the partner team developers to fix this issue if they want.

General opinion & you may also be aware..

RFC 7519 spec  shows exp and iat claim values must be NumericDate values & check https://www.rfc-editor.org/rfc/rfc7519#section-2 section for NumericDate.

 NumericDate
      A JSON numeric value representing the number of seconds from
      1970-01-01T00:00:00Z UTC until the specified UTC date/time,
      ignoring leap seconds.  This is equivalent to the IEEE Std 1003.1,
      2013 Edition [POSIX.1] definition "Seconds Since the Epoch", in
      which each day is accounted for by exactly 86400 seconds, other
      than that non-integer values can be represented.  See RFC 3339
      [RFC3339] for details regarding date/times in general and UTC in
      particular.

Why not forward the spec & make awareness on the proper usage? Sometimes it helps them & apply fix at partner end.Think about it.

thank you for your reponse, im totally okey with you,  but this is not possible...