on main help sign in
fix(oauth): harden IsExpired with minimum buffer and ExpiresIn guard
d87a632Kieran Klukas
internal/oauth/token.go+21−3
@@ -1,9 +1,15 @@
1package oauth
1package oauth
2
2
3import (
3import (
4+ "log/slog"
4 "time"
5 "time"
5)
6)
6
7
8+// minRefreshBuffer is the minimum number of seconds before actual
9+// expiry at which IsExpired returns true. Prevents very short-lived
10+// tokens from having a meaningless refresh window.
11+const minRefreshBuffer = 30
12+
7// Token represents an OAuth2 token.
13// Token represents an OAuth2 token.
8type Token struct {
14type Token struct {
9 AccessToken string `json:"access_token"`
15 AccessToken string `json:"access_token"`
@@ -12,14 +18,26 @@ type Token struct {
12 ExpiresAt int64 `json:"expires_at"`
18 ExpiresAt int64 `json:"expires_at"`
13}
19}
14
20
15−// SetExpiresAt calculates and sets the ExpiresAt field based on the current time and ExpiresIn.
21+// SetExpiresAt calculates and sets the ExpiresAt field based on the
22+// current time and ExpiresIn. If ExpiresIn is zero or negative, it
23+// defaults to 3600 seconds and logs a warning.
16func (t *Token) SetExpiresAt() {
24func (t *Token) SetExpiresAt() {
25+ if t.ExpiresIn <= 0 {
26+ slog.Warn("OAuth token has invalid expires_in, defaulting to 3600s", "expires_in", t.ExpiresIn)
27+ t.ExpiresIn = 3600
28+ }
17 t.ExpiresAt = time.Now().Add(time.Duration(t.ExpiresIn) * time.Second).Unix()
29 t.ExpiresAt = time.Now().Add(time.Duration(t.ExpiresIn) * time.Second).Unix()
18}
30}
19
31
20−// IsExpired checks if the token is expired or about to expire (within 10% of its lifetime).
32+// IsExpired checks if the token is expired or about to expire. It
33+// uses a buffer of max(expires_in/10, minRefreshBuffer) seconds to
34+// trigger proactive refresh before the token actually expires.
21func (t *Token) IsExpired() bool {
35func (t *Token) IsExpired() bool {
36+ buffer := int64(t.ExpiresIn) / 10
37+ if buffer < minRefreshBuffer {
38+ buffer = minRefreshBuffer
39+ }
22− return time.Now().Unix() >= (t.ExpiresAt - int64(t.ExpiresIn)/10)
40+ return time.Now().Unix() >= (t.ExpiresAt - buffer)
23}
41}
24
42
25// SetExpiresIn calculates and sets the ExpiresIn field based on the ExpiresAt field.
43// SetExpiresIn calculates and sets the ExpiresIn field based on the ExpiresAt field.