- πΊπΈUnited States torgosPizza Portland, OR
We are currently experiencing this on our live production site (Drupal 7) and based on what I see in the D8 code, the latest version of the module may suffer from a similar problem.
Right now, applying patches adding classes such as
JwtAccessTokenStorage
are helpful, but the issue lies in the fact that the private and public keys are both "global". Most of the time this works especially if users are not hitting these frequently.But, we have seen one particular scenario play out quite frequently (using JWTs, access token expiry = 3600, refresh token = 90 days):
1. A user generates a JWT right before new server keys are needed. (Example: if server keys get generated every day at 23:59:59, our test user should generate their token at 22:59:59.)
2. Server cron runs and new keys are generated.
3. The user continues to make requests to endpoints with the JWT from Step 1 because it is valid for 2 more hours.Expected result: the access token (which is not yet expired) is accepted as valid.
Actual result: "invalid_token" error because the global keys no longer decrypt the token.
In the D7 module this is due to 1) the keys being global and 2) not being stored with the token. Even when we have configured a Public Key in the settings area, this key is ignored in the encode/decode process. It does appear the latest code follows a similar pattern:
public function getPublicKey($client_id = NULL) { // The library allows for per-client keys. The module uses global keys that // are regenerated every day, following Google's example. $keys = Utility::getKeys(); return $keys['public_key']; }
I'm not sure how to properly address this, but part of the issue IMO seems to be to ensure that the public key used to encode the JWT is stored in the token itself on the server. If that is not possible, it should be changed so that the public key is NOT regenerated so frequently; while the code block's comments above indicate we are "following Google's example," what the Drupal module neglected to copy was low frequency of public key rotation:
Since Google changes its public keys only infrequently, you can cache them using the cache directives of the HTTP response ...
In the Drupal side of things, private and public keys are rotated every day during oauth2_server_cron(), resulting in frequent access tokens being erroneously seen as "invalid". One other solution might be to make the access tokens only expire after 30 minutes, but we sell video content that is sometimes 2 hours in length, and it's possible that this could cause errors while the user is viewing their purchased content. In my opinion the keys system should be made more flexible to account for this behavior.
- πΊπΈUnited States torgosPizza Portland, OR
This seems related and relevant: π The JWT must contain the kid Active