-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathleeway.go
More file actions
84 lines (78 loc) · 2.93 KB
/
leeway.go
File metadata and controls
84 lines (78 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package jwt
import (
"errors"
"time"
)
// Leeway creates a TokenValidator that adds a buffer time before token expiration.
//
// This validator provides "leeway" by rejecting tokens that will expire within
// the specified duration, even if they are technically still valid. This is useful
// to prevent race conditions where a token expires between validation and use.
//
// The validation logic: if (now + leeway) > expiration_time, reject the token.
//
// Common use cases:
// - Database operations that might take several seconds to complete
// - API calls that involve multiple service hops
// - Batch processing where token might expire during execution
// - Network latency compensation in distributed systems
//
// Example:
//
// // Reject tokens expiring within 30 seconds
// leewayValidator := jwt.Leeway(30 * time.Second)
//
// verifiedToken, err := jwt.Verify(alg, key, token, leewayValidator)
// // Token is rejected if it expires within 30 seconds
//
// Note: This only affects tokens that have an "exp" claim. Tokens without
// expiration are not affected by leeway validation.
func Leeway(leeway time.Duration) TokenValidatorFunc {
return func(_ []byte, standardClaims Claims, err error) error {
if err == nil {
if standardClaims.Expiry > 0 {
if Clock().Add(leeway).Round(time.Second).Unix() > standardClaims.Expiry {
return ErrExpired
}
}
}
return err
}
}
// Future creates a TokenValidator that allows tokens issued slightly in the future.
//
// This validator provides tolerance for clock skew between different systems
// by accepting tokens that appear to be issued in the future, up to the specified duration.
// Without this tolerance, legitimate tokens might be rejected due to minor time differences
// between servers.
//
// The validation logic: if (now + duration) < issued_at_time, still reject the token.
// Otherwise, accept tokens that would normally be rejected for future issuance.
//
// Common use cases:
// - Compensating for clock drift between authentication and resource servers
// - Handling timezone discrepancies in distributed systems
// - Allowing for minor network delays in token propagation
// - Testing scenarios with slightly misaligned system clocks
//
// Example:
//
// // Allow tokens issued up to 60 seconds in the future
// futureValidator := jwt.Future(60 * time.Second)
//
// verifiedToken, err := jwt.Verify(alg, key, token, futureValidator)
// // Token is accepted even if "iat" is up to 60 seconds in the future
//
// Note: This only affects tokens that would otherwise fail with ErrIssuedInTheFuture.
// Tokens without "iat" claims or with past issuance times are unaffected.
func Future(dur time.Duration) TokenValidatorFunc {
return func(_ []byte, standardClaims Claims, err error) error {
if errors.Is(err, ErrIssuedInTheFuture) {
if Clock().Add(dur).Round(time.Second).Unix() < standardClaims.IssuedAt {
return ErrIssuedInTheFuture
}
return nil
}
return err
}
}