ory/fosite

private_key_jwt assetion tokens can have unbounded expiration which can fill data store

Closed this issue · 3 comments

Preflight checklist

Ory Network Project

No response

Describe your problem

I noticed in current fosite implementation (unless I missed something) that there is no limitation on the maximum expiration time for private_key_jwt assertion tokens. They have to be stored in the database until they expire which means that this can potentially make storage requirements for them large.

Describe your ideal solution

In practice, those tokens should not have long expiration times. They should be generated anyway again and again. Auth0 for example forces 5 minutes maximum expiration time (example I found first online).

I suggest we introduce some maximum expiration time through config which allows one to extend it if somebody really wants a long expiration time. But the default should be something short, like 5 minutes to allow for clock skew and stuff.

Workarounds or alternatives

I cannot find any. We just have to store tokens until expiration.

Version

latest master

Additional Context

No response

Related: https://datatracker.ietf.org/doc/html/rfc7523#section-3

        Note that the authorization server may reject JWTs
        with an "exp" claim value that is unreasonably far in the
        future.

In our customized implementation of client authentication, which includes other stuff like tls_client_auth and the ability to choose between custom trust stores and jwks/jwks_uri, we introduced a new configurator interface for exactly the purpose that @james-d-elliott highlighted. We then check for a few things -

  1. iat unreasonably far in the past
  2. exp unreasonably far in the future
  3. (exp-iat) longer than a configured allowed lifetime value to prevent particularly long-lived JWTs and to enforce "freshness"

We happen to do this for all incoming JWTs, not just the client_assertion used for private_key_jwt. There are other practical things to consider adding like a clock skew setting.

It seems I missed this. There is GrantTypeJWTBearerMaxDuration config which seems to control this and it defaults to 1 day.