Skip to content
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

Add option to change time precision for creation/parsing tokens. #400

Open
ajermaky opened this issue Jul 23, 2024 · 5 comments
Open

Add option to change time precision for creation/parsing tokens. #400

ajermaky opened this issue Jul 23, 2024 · 5 comments

Comments

@ajermaky
Copy link
Contributor

We can currently change the precision of timestamps getting serialized by modifying TimePrecision here.
However we are running into an issue where we have to serialize/validate different jwt tokens of various precisions (i.e. seconds, milliseconds).

As a work around, we are creating our own version of jwt.RegisteredClaims that serializes/deserializes times based on the precision that we want. However it would be nice if we can include a time precision option in jwt.New or jwt.ParseWithClaims

@oxisto
Copy link
Collaborator

oxisto commented Jul 23, 2024

I had a similar feature in mind a while ago. This was previously not possible, but recently we changed the way the parser/validator works and both can now be supplied with options that are accessible in the respective (de)serialisation functions, so this might work.

You could probably take some hints from #301. Specifically you need to apply the token options to the created token like this (which is not yet in main):
https://github.com/golang-jwt/jwt/pull/301/files#diff-2feccbe0109db2f6b93af0c4afed26af571a61438266ebd8690bf669c75d2874R63-R66

Just to add, I am not quite sure why, but after writing these lines I think there was still some kind of issue with this we could not work around... But I cannot remember, so feel free to try it ;)

@ajermaky
Copy link
Contributor Author

makes sense! Will take a crack and give and update!

@oxisto
Copy link
Collaborator

oxisto commented Jul 27, 2024

Hmm I remember now why this probably won’t work. You will not have access to the options in the unmarshal func of NumericDate. I would be interested in how you solved this problem in your workaround.

@ajermaky
Copy link
Contributor Author

ajermaky commented Jul 27, 2024

You will not have access to the options in the unmarshal func of NumericDate.

Can Confirm, this is the issue i'm hitting against!

I am mainly working with the idea to add a precision field to NumericDate and remove any calls to truncate the time until it gets fetched, i.e.

type NumericDate struct {
	t time.Time
	precision time.Duration
}

func (d *NumericDate) Time() time.Time{
    return d.t.Truncate(d.precision)

}

But like you said, parser won't be able to control the unmarshal issue.
The one idea I had was to update the claims interface as:

type Claims interface {
	GetExpirationTime() (*NumericDate, error)
	GetIssuedAt() (*NumericDate, error)
	GetNotBefore() (*NumericDate, error)
	GetIssuer() (string, error)
	GetSubject() (string, error)
	GetAudience() (ClaimStrings, error)
	SetPrecision(time.Duration)
}

And registered claims being something like:


func (c RegisteredClaims) SetPrecision(precision time.Duration) {
	c.ExpiresAt.precision = precision
	c.NotBefore.precision = precision
	c.IssuedAt.precision = precision
}

And inside the parser, we call it before getting unmarshalled i.e.

token.Claims = claims
prec = // if options nil, use default time.Second
token.Claims.SetPrecision(prec)
...
err = json.Unmarshal(claimBytes, &claims)

That looks like it may work, but it feels a bit wonky.
I think specifically main issues:

  • This works very well for RegisteredClaims - not so much for MapClaims. There is maybe a hack where we store an additional precision field in the map, but I think that's dangerous to do.
  • Adds additional complexity for users implementing their own claims
  • Would require us to lose embedding of time object in NumericDate (although I can see a usecase where we set precision and truncate in place)
  • This would only help with NumericDate that are part of Claims interface - if we define any other NumericDate in a custom claims, there isn't really a way for us to systematically update it.

I do think adding a precision field on the NumericDate object would be a step in the right direction, as that would give us more control, but not seeing a way for the parser to control that.

Curious on your thoughts!

@oxisto
Copy link
Collaborator

oxisto commented Aug 29, 2024

we are probably stuck here until the v2 version of json arrives with options. See https://pkg.go.dev/github.com/go-json-experiment/json#Options

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

No branches or pull requests

2 participants