@@ -14,6 +14,9 @@ import (
14
14
"time"
15
15
)
16
16
17
+ // ErrNoToken is returned when no token is available in the token store
18
+ var ErrNoToken = errors .New ("no token available" )
19
+
17
20
// OAuthConfig holds the OAuth configuration for the client
18
21
type OAuthConfig struct {
19
22
// ClientID is the OAuth client ID
@@ -33,11 +36,25 @@ type OAuthConfig struct {
33
36
PKCEEnabled bool
34
37
}
35
38
36
- // TokenStore is an interface for storing and retrieving OAuth tokens
39
+ // TokenStore is an interface for storing and retrieving OAuth tokens.
40
+ //
41
+ // Implementations must:
42
+ // - Honor context cancellation and deadlines, returning context.Canceled
43
+ // or context.DeadlineExceeded as appropriate
44
+ // - Return ErrNoToken (or a sentinel error that wraps it) when no token
45
+ // is available, rather than conflating this with other operational errors
46
+ // - Properly propagate all other errors (database failures, I/O errors, etc.)
47
+ // - Check ctx.Done() before performing operations and return ctx.Err() if cancelled
37
48
type TokenStore interface {
38
- // GetToken returns the current token
49
+ // GetToken returns the current token.
50
+ // Returns ErrNoToken if no token is available.
51
+ // Returns context.Canceled or context.DeadlineExceeded if ctx is cancelled.
52
+ // Returns other errors for operational failures (I/O, database, etc.).
39
53
GetToken (ctx context.Context ) (* Token , error )
40
- // SaveToken saves a token
54
+
55
+ // SaveToken saves a token.
56
+ // Returns context.Canceled or context.DeadlineExceeded if ctx is cancelled.
57
+ // Returns other errors for operational failures (I/O, database, etc.).
41
58
SaveToken (ctx context.Context , token * Token ) error
42
59
}
43
60
@@ -76,20 +93,23 @@ func NewMemoryTokenStore() *MemoryTokenStore {
76
93
return & MemoryTokenStore {}
77
94
}
78
95
79
- // GetToken returns the current token
96
+ // GetToken returns the current token.
97
+ // Returns ErrNoToken if no token is available.
98
+ // Returns context.Canceled or context.DeadlineExceeded if ctx is cancelled.
80
99
func (s * MemoryTokenStore ) GetToken (ctx context.Context ) (* Token , error ) {
81
100
if err := ctx .Err (); err != nil {
82
101
return nil , err
83
102
}
84
103
s .mu .RLock ()
85
104
defer s .mu .RUnlock ()
86
105
if s .token == nil {
87
- return nil , errors . New ( "no token available" )
106
+ return nil , ErrNoToken
88
107
}
89
108
return s .token , nil
90
109
}
91
110
92
- // SaveToken saves a token
111
+ // SaveToken saves a token.
112
+ // Returns context.Canceled or context.DeadlineExceeded if ctx is cancelled.
93
113
func (s * MemoryTokenStore ) SaveToken (ctx context.Context , token * Token ) error {
94
114
if err := ctx .Err (); err != nil {
95
115
return err
@@ -157,10 +177,8 @@ func (h *OAuthHandler) GetAuthorizationHeader(ctx context.Context) (string, erro
157
177
// getValidToken returns a valid token, refreshing if necessary
158
178
func (h * OAuthHandler ) getValidToken (ctx context.Context ) (* Token , error ) {
159
179
token , err := h .config .TokenStore .GetToken (ctx )
160
- if err != nil {
161
- if errors .Is (err , context .Canceled ) || errors .Is (err , context .DeadlineExceeded ) {
162
- return nil , err
163
- }
180
+ if err != nil && ! errors .Is (err , ErrNoToken ) {
181
+ return nil , err
164
182
}
165
183
if err == nil && ! token .IsExpired () && token .AccessToken != "" {
166
184
return token , nil
@@ -229,12 +247,8 @@ func (h *OAuthHandler) refreshToken(ctx context.Context, refreshToken string) (*
229
247
}
230
248
231
249
// If no new refresh token is provided, keep the old one
232
- oldToken , oldErr := h .config .TokenStore .GetToken (ctx )
233
- if oldErr != nil && (errors .Is (oldErr , context .Canceled ) || errors .Is (oldErr , context .DeadlineExceeded )) {
234
- return nil , oldErr
235
- }
236
- if tokenResp .RefreshToken == "" && oldToken != nil {
237
- tokenResp .RefreshToken = oldToken .RefreshToken
250
+ if tokenResp .RefreshToken == "" {
251
+ tokenResp .RefreshToken = refreshToken
238
252
}
239
253
240
254
// Save the token
0 commit comments