Refresh token with GenerateJWT policy

rajeevyes
Participant II

Has anybody implemented a refreshtoken using GenerateJWT policy?

The normal GenerateAccessToken policy has an option to generate a refresh token and send it along with access token response but that option is not there with GenerateJWT policy. Any leads on this would be much appreciated.

Regards,

Rajeev S

0 8 1,545
8 REPLIES 8

GenerateJWT just generates a JWT, a signed payload. You provide the payload to sign.

If you would like to include an access token into that JWT, then you will need to precede the call to GenerateJWT with a call to OAuthV2/GenerateAccessToken, and then embed the access token and the refresh token into the payload for the JWT.

@Dino-at-Google The intention is not to include access token into JWT. We are generating a JWT with user id claims( you can say its ID token and not access token). Similar to how we use refresh token to extend the expiry of the opaque access token, how do we extend the expiry of apigee generated JWTs. Please do note that the client does'nt send api secret for Apigee to generate access tokens/refresh tokens using normal GenerateAccessToken policy.

Hope i am clear.

Hi - I'm not quite clear on exactly what's going on.

I understand you're dealing with a JWT with id claims, an ID token.

There is no "refresh" token in a JWT. Normally, to get a new JWT ID Token, your system would ask the user to re-authenticate. Login again, something like that.

Beyond that I don't understand exactly what you're aiming at. but maybe I can offer some additional information that might help.

it is not possible to "extend the expiry" of an already-issued JWT. The JWT is a signed entity. Any modification of the claims in the JWT will mean the signature will not match. A receiver of a JWT, when trying to verify the signature, will find that the signature does not match, and will be compelled to reject the JWT.

It is possible for you to use the GenerateJWT policy in Apigee Edge to generate and sign a JWT that includes NO EXPIRY. Or, it is possible for you to configure any expiry you like. But once issued, the JWT expiry cannot be changed. This is true for any issuer. It is a fetaure of the JWT standard, not an implication of the Apigee implementation. This is just how JWTs (or in fact, any digitally-signed material) work, anywhere.

@Dino-at-Google Currently client is re-authenticating after JWT expiry. Currently JWT expiry is set to 1 hour and its not a good user-experience to ask users to authenticate after every hour. Thanks for the response. Ill look at increasing the JWT expiry time.

Hi @Rajeev S. If the client doesn't send the client_id AND client_secret, how can you be sure the refresh call is not from the only client allowed to refresh? Are you using client certs in addition? Or is there an assumption that the call is from the same client because they have the client_id and token? Client_ID is sent in URI for authcode grant so that value should be considered public.

Also, OpenID Connect (ID token) is stacked on top oAuth2 so I would just follow the spec for that instead of trying to roll your own implementation of what you have described.

Off the top of my head, this might work, but it would be prudent to run it by a third party security team for review and approval:

use the Auth Code grant type for token endpoint plus the following.

option 1: Opaque Apigee Edge token with ID token as JWT and embedded into edge token as a custom attribute.

option 2: Use JWT for entire token and add access token, refresh token, and id token as claims. Set the JWT token expiry time to just before the edge access token expiry time. See @Dino-at-Google's answer above.

Hi @Dino-at-Google, I am interested in you approach of using refresh token. Can you please give me more details on it?

sidd-harth
Participant V

Hi @Rajeev S , as per previous posts, I understand that you are looking to generate a new JWT token using a refresh_token.

In OAuth, with access_token we can also get a refresh_token, which can be used to get a new token.

As said by Dino,

There is no "refresh" token in a JWT. Normally, to get a new JWT ID Token, your system would ask the user to re-authenticate. Login again, something like that.

But if you still want to refresh your JWT. You can try below steps.

In JWT, we do not get a refresh_token. So we will use the original JWT, decode it to check the expire time and generate a new token based on few Conditions,

  1. Create a new ConditonalFlow with pathsuffix as "/refreshToken"
  2. Add a DecodeJWT Policy to get all the JWT attributes.
  3. Add a RaiseFault Policy with Condition to check if received token is expired or not using "is_expired" variable. Raise a fault if the token is not yet expired.
  4. Add GenerateJWT Policy, generate a new token with same claims/details(which you got in Step2) with a lesser expire time.

I did not try this, so I am not sure if it works or not.

I am SURE, that technically, this would work. If you do this, be careful.

If you don't take care to track the number of times a JWT has been "Refreshed" in this way, you will essentially have a never-expiring token. It is a token that can always be refreshed, forever and ever. That is probably not what you want. So you would need to insert a "refresh count" or something like that as a claim into the signed JWT, and you would need to enforce a limit on the number of refreshes you allow.

Also I wouldn't want the logic to "refresh" a JWT in this way only if it were expired. I Would want the logic to allow refresh only if the JWT is NOT expired.

EVEN IF YOU DO THAT, it raises the question - why not just issue one JWT with an expiry that is N* the original expiry?

Suppose the JWT expires in 24 hours and you allow 5 "refreshes". Why not just issue the single JWT and allow it to expire in 5*24 hours = 120 hours ? It saves you a lot of trouble.