How to invalidate/revoke JWT token after user logout

darpanjain420
Participant III

In my application APIGEE is used as the authentication layer for users. We are using JWT token as means for authentication at service end. There is a requirement such that if the user logs out and the JWT token is not expired, then the application should call the APIGEE edge for the invalidation of the JWT issued earlier.

Is there any way to achieve this scenario?

Solved Solved
0 9 19.4K
2 ACCEPTED SOLUTIONS

JWT Cannot be invalidated. I have written about this elsewhere.

You can sort of simulate invalidation of a JWT, for a particular verifying party, by storing the JWT ID (jti claim) or equivalent, into a "revoked" list. For example, in a cache stored in Apigee Edge using the PopulateCache policy. Use a TTL that is longer than the JWT Expiry. (This will not work well if the JWT does not have an expiry!)

Then, to verify the JWT, you would need 2 steps in your API Proxy flow:

  • extract the JTI (or other unique identifier) from the JWT using the DecodeJWT policy, and check the Revoked list (via the LookupCache policy) to see if that key is present. If it is present, then the JWT has been marked "revoked", so the API proxy should respond accordingly.
  • otherwise use VerifyJWT as normal.

Any other party that verifies the JWT will not consider it to be revoked.

View solution in original post

sidd-harth
Participant V

Darpan, I have handled JWT in the past within a MEAN Stack App. It was a PoC and security was not a high priority so I have used cookies to handle JWT. When the user logs out, I used to simply clear the cookie.

Dino that is a good solution for indirectly revoking a JWT in some exceptional cases. I have built a sample proxy based on your steps. Can you please explain why the PopulateCache should have a longer TTL than the JWT Expiry?

jwt-rev4-2019-04-03.zip

View solution in original post

9 REPLIES 9

@darpan jain

It is possible to invalidate the access token using the OAuthV2 policy with operation as

<Operation>InvalidateToken</Operation>

You can expose an api endpoint to invalidate the token and make a call to this endpoint when the user logs out.

Nagashree, yes we can invalidate OAuth tokens but AFAIK there is no OOTB option to revoke JWT tokens in Apigee.

We can create a custom flow and with the help of Decode and Generate JWT policies and few conditions we can invalidate JWT, but I guess it is not a good approach.

@darpan jain, if the JWT token generated by Apigee?

Right, I missed the part on the identity provider. Assumed its an external identity provider. For an external identity provider, you can handle this through the InvalidateToken as Apigee will only be storing the token.

@Siddharth Barahalikar

The jwt token is generated by apigee itself. Could you please elaborate on the custom flow which can achieve the invalidation of the JWT token?

@Nagashree B OAuth is not something we have used or can be used. We have to use the JWT token concept only.

JWT Cannot be invalidated. I have written about this elsewhere.

You can sort of simulate invalidation of a JWT, for a particular verifying party, by storing the JWT ID (jti claim) or equivalent, into a "revoked" list. For example, in a cache stored in Apigee Edge using the PopulateCache policy. Use a TTL that is longer than the JWT Expiry. (This will not work well if the JWT does not have an expiry!)

Then, to verify the JWT, you would need 2 steps in your API Proxy flow:

  • extract the JTI (or other unique identifier) from the JWT using the DecodeJWT policy, and check the Revoked list (via the LookupCache policy) to see if that key is present. If it is present, then the JWT has been marked "revoked", so the API proxy should respond accordingly.
  • otherwise use VerifyJWT as normal.

Any other party that verifies the JWT will not consider it to be revoked.

Dino ,

Is this the only solution ? Do we need to maintain all the JWTs in Cassandra within Apigee? and load them to cache the blacklisted ones and periodically refresh them?

No, there are lots of options. For example, you could embed into the JWT a reference to another identifier (an OAuth token, a session key? something like that) that COULD get invalidated.

For example, you could

  • generate an OAuth token in Apigee Edge. This automatically stores the token in the token store. You mentioned Cassandra, but that is an implementation detail; it is not necessary to consider that detail here.
  • generate the JWT and embed the Oauth token in the signed JWT before signing.
  • After the API proxy verifies the JWT (VerifyJWT), follow that with a second step that verifies that token (OAuthV2/VerifyAccessToken). Only proceed if both things are true: (1) the JWT is valid and not expired and is signed by the expetced signer; and (2) the token is valid.
  • If you want to invalidate the OAuth token you can use the usual process in Apigee Edge to do so.

This is a key point: JWT in particular are not designed to be "revokable". Sure you can build a revocation convention around a JWT, but the standard is not designed with that in mind, so the JWT standard provides no help for you in doing this. JWT are like cash money. Nobody revokes a specific $10 bill.

Imagine writing a number on that $10 bill, and establishing a convention that, before the recipient accepts the $10 bill, they have to look at the number and determine if that number is still good, before accepting the $10 bill as currency. You can imagine how this would work, but it wouldn't be very scalable. You could employ the same approach with JWT, by including an additional arbitrary claim in the signed payload.

By adding in the second step, you defeat many of the advantages of the JWT concept. This may or may not be important to you. You'd need to have a good think about why you're using JWT in the first place.

sidd-harth
Participant V

Darpan, I have handled JWT in the past within a MEAN Stack App. It was a PoC and security was not a high priority so I have used cookies to handle JWT. When the user logs out, I used to simply clear the cookie.

Dino that is a good solution for indirectly revoking a JWT in some exceptional cases. I have built a sample proxy based on your steps. Can you please explain why the PopulateCache should have a longer TTL than the JWT Expiry?

jwt-rev4-2019-04-03.zip

I should say "at least as long as". For safety, we could have a TTL that is 1s longer than the expiry of the JWT. That way if the "revoked**" JWT is presented, the blacklist will contain the correct jti at least until expiry of the JWT. When the cache TTL expires, even if the "revoked**" JWT is presented again, it will be rejected because it is expired.

If the JWT does not expire, that is a real problem. It means an always-increasing blacklist of JWT, and that can grow without bound, which doesn't work in a real world system.