Skip to content
This repository has been archived by the owner on May 21, 2022. It is now read-only.

"Token used before issued" when checking 'iat' #314

Open
wolfrace opened this issue Feb 15, 2019 · 9 comments
Open

"Token used before issued" when checking 'iat' #314

wolfrace opened this issue Feb 15, 2019 · 9 comments

Comments

@wolfrace
Copy link

wolfrace commented Feb 15, 2019

I have out of sync problem.
Time on php server is different for a fraction of a second and because of this there is a problem when checking the token Token used before issued.

Is it possible to make the check less strict?

func verifyIat(iat int64, now int64, required bool) bool {
	if iat == 0 {
		return !required
	}
	return now >= iat
}

I used this workaround:

jwt.TimeFunc = func() time.Time {
		return time.Now().Add(time.Second)
	}

What would you advise me?

@suessflorian
Copy link

suessflorian commented Mar 3, 2019

Something to add to this conversation perhaps, I noticed that changing the local machines time to Apple America/U.S solves my problem...

image

@suessflorian
Copy link

I originally was a few milliseconds off (the now and iat stamps), now they are consistently the same.

@dgrijalva
Copy link
Owner

Issued at checking will be removed in v4, per the jwt spec.

@montanaflynn
Copy link

@dgrijalva is there a workaround available now? I'm also seeing this issue on a small amount of requests.

@dgrijalva
Copy link
Owner

Simplest workaround is probably to wrap your claims type in something custom that bypasses the IAT check. Here's a lazy example I didn't actually test. Something like the following should work:

type MyClaims struct {
*jwt.StandardClaims
}

func (c *MyClaims) Valid()bool {
    var leeway = 10
    c.StandardClaims.IssuedAt -= leeway
   valid := c.StandardClaims.Valid()
   c.StandardClaims.IssuedAt += leeway
  return valid
}

@teuber789
Copy link

FWIW - I had this problem and it turned out to be the internal clock on my EC2 instance. Following this guide solved the problem.

@kristopher
Copy link

Ran into this as well, any plans to support some amount of clock drift? 0 - 500ms isn't that uncommon with ntp.

@pawelkowalak
Copy link

pawelkowalak commented Jun 29, 2020

Another workaround:

token, err := jwt.Parse(t, func(token *jwt.Token) (interface{}, error) {
...
}
if err != nil {
	e, ok := err.(*jwt.ValidationError)
	if !ok || ok && e.Errors & jwt.ValidationErrorIssuedAt == 0 { // Don't report error that token used before issued.
		return err
	}
}

@scarlac
Copy link

scarlac commented Apr 3, 2021

There's a caveat for @pawelkowalak's suggestion in that .Valid needs to be set to true if that's the only error. Otherwise you may later do if token.Valid { and find that it fails despite a lack of err.
Another workaround is to remove iat from the token prior to validation:

request.ParseFromRequest(..., func(token *jwt.Token) (interface{}, error) {
	mapClaims := token.Claims.(jwt.MapClaims)
	delete(mapClaims, "iat")
	// ...
})

This approach works because the keyFunc callback is called internally in the library before running validation. This allows using the callback to modify the claims after it has been created but before it's being validated.
You can also chose to simply modify it directly instead of deleting it with this pseudo code: (mapClaims["iat"].(float64)) -= 5 which subtracts 5 seconds from the issue time.

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

No branches or pull requests

8 participants