Skip to content

injecting clock when we are generating the JWT token #2004

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

AlessandroMinoccheri
Copy link

In this PR I am trying to solve this issue: #1950
By injecting clock into the token generation

@AlessandroMinoccheri AlessandroMinoccheri force-pushed the injecting-clock-into-token-generation-code branch from b7a3b3a to d132a7a Compare May 12, 2025 19:41
@AlessandroMinoccheri AlessandroMinoccheri changed the title injecting clock when we are generating the token injecting clock when we are generating the JWT token May 12, 2025
@AlessandroMinoccheri AlessandroMinoccheri marked this pull request as ready for review May 12, 2025 19:42
@jgrandja
Copy link
Collaborator

@AlessandroMinoccheri Apologies for the late response but I've been busy preparing for the 1.5 release this Tuesday. I will likely review this next week.

@jgrandja jgrandja added type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged labels May 15, 2025
@jgrandja jgrandja self-assigned this May 15, 2025

private OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer;

/**
* Constructs a {@code JwtGenerator} using the provided parameters.
* @param jwtEncoder the jwt encoder
*/
public JwtGenerator(JwtEncoder jwtEncoder) {
public JwtGenerator(JwtEncoder jwtEncoder, Clock clock) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change. Alternatively, we could add an overloaded constructor with JwtEncoder, Clock, but we typically favour setters (e.g. setClock(Clock)) when the attribute is not required.

However, even with the setter approach, there are too many classes that require this public API change and my preference would be to minimize this.

Another possible solution would be to obtain the Clock from AuthorizationServerContext, which is available in OAuth2TokenContext. Thoughts?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @jgrandja for your comment.

Let me try to summarize to understand if I got your points:

  • adding a new param it's a breaking change and we are trying to avoid it
  • we can add a setter for the clock but this will be an open public method and we need to minimize them
    How much is problematic to add a new public method in terms of integrations?
    For me, this is the best option on the table, devs will decide if they would like to inject the Clock or not.
    I am not a big fun of setters by the way.
  • we can get the clock from one of the contexts
    Uhm... taking things from contexts seems everytime and overhead of resources and it can create side effects. Also, it can complicate tests and integrations..

Another option..
what about add the parameter Clock optional?

   // Constructor with optional Clock
    public JwtGenerator(JwtEncoder jwtEncoder) {
        this(jwtEncoder, Clock.systemUTC()); // Default to system UTC clock
    }

    // Constructor with explicit Clock
    public JwtGenerator(JwtEncoder jwtEncoder, Clock clock) {
        this.jwtEncoder = jwtEncoder;
        this.clock = clock;
    }

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How much is problematic to add a new public method in terms of integrations?

It's not problematic but configuration could be verbose as there are up to 6x OAuth2TokenGenerator that would need to be configured.

taking things from contexts seems everytime and overhead of resources and it can create side effects.

I'm not sure I understand. Why do you think it would be an overhead in resources and what side effects are you referring to?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I will rephrase my sentence with more info.
For me, use context has different cons:
AuthorizationServerContext is request-scoped

  • The AuthorizationServerContext is tied to the current request lifecycle.
  • If you try to extract the Clock from this context outside of a token generation request (e.g. in background jobs, unit tests, or beans instantiated at application startup), the context won't exist, leading to IllegalStateException or null values.

It violates separation of concerns

  • The Clock is a core time abstraction often needed for testing, validation, and system logic.

  • Getting it from a request-scoped context couples your logic too tightly to the OAuth2 token issuance flow, making your code harder to test.

  • When using Clock from AuthorizationServerContext, you cannot easily inject mock clocks in unit or integration tests.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All very good points @AlessandroMinoccheri.

Ok, let's keep it simple and add setClock() to all OAuth2TokenGenerator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants