6
6
"time"
7
7
)
8
8
9
+ const MinTokenTTL = 30 * time .Minute
10
+
9
11
// TokenManagerOptions is a struct that contains the options for the TokenManager.
10
12
type TokenManagerOptions struct {
11
13
// ExpirationRefreshRatio is the ratio of the token expiration time to refresh the token.
@@ -15,10 +17,10 @@ type TokenManagerOptions struct {
15
17
// the token will be refreshed after 30 minutes.
16
18
ExpirationRefreshRatio float64
17
19
18
- // ParseToken is a function that parses the raw token and returns a Token object.
20
+ // TokenParser is a function that parses the raw token and returns a Token object.
19
21
// The function takes the raw token as a string and returns a Token object and an error.
20
22
// If this function is not provided, the default implementation will be used.
21
- ParseToken TokenParserFunc
23
+ TokenParser TokenParserFunc
22
24
23
25
// RetryOptions is a struct that contains the options for retrying the token request.
24
26
// It contains the maximum number of attempts, initial delay, maximum delay, and backoff multiplier.
@@ -49,14 +51,14 @@ type TokenManager interface {
49
51
}
50
52
51
53
// defaultTokenParser is a function that parses the raw token and returns Token object.
52
- var defaultTokenParser = func (rawToken string ) (* Token , error ) {
54
+ var defaultTokenParser = func (rawToken string , expiresOn time. Time ) (* Token , error ) {
53
55
// Parse the token and return the username and password.
54
56
// This is a placeholder implementation.
55
57
return & Token {
56
58
Username : "username" ,
57
59
Password : "password" ,
58
- ExpiresAt : time . Now (). Add ( 1 * time . Hour ). Unix () ,
59
- TTL : 3600 ,
60
+ ExpiresOn : expiresOn ,
61
+ TTL : expiresOn . Unix () - time . Now (). Unix () ,
60
62
RawToken : rawToken ,
61
63
}, nil
62
64
}
@@ -66,14 +68,14 @@ var defaultTokenParser = func(rawToken string) (*Token, error) {
66
68
// The IdentityProvider is used to obtain the token, and the TokenManagerOptions contains options for the TokenManager.
67
69
// The TokenManager is responsible for managing the token and refreshing it when necessary.
68
70
func NewTokenManager (idp IdentityProvider , options TokenManagerOptions ) TokenManager {
69
- tokenParser := options .ParseToken
70
- if tokenParser == nil {
71
- tokenParser = defaultTokenParser
72
- }
71
+ tokenParser := defaultTokenParserOr (options .TokenParser )
72
+ retryOptions := defaultRetryOptionsOr (options .RetryOptions )
73
+
73
74
return & entraidTokenManager {
74
- idp : idp ,
75
- token : nil ,
76
- TokenParser : tokenParser ,
75
+ idp : idp ,
76
+ token : nil ,
77
+ tokenParser : tokenParser ,
78
+ retryOptions : retryOptions ,
77
79
}
78
80
}
79
81
@@ -82,7 +84,13 @@ type entraidTokenManager struct {
82
84
idp IdentityProvider
83
85
token * Token
84
86
// TokenParser is a function that parses the token.
85
- TokenParser TokenParserFunc
87
+ tokenParser TokenParserFunc
88
+
89
+ // retryOptions is a struct that contains the options for retrying the token request.
90
+ // It contains the maximum number of attempts, initial delay, maximum delay, and backoff multiplier.
91
+ // The default values are 3 attempts, 1000 ms initial delay, 10000 ms maximum delay, and 2.0 backoff multiplier.
92
+ // The values can be overridden by the user.
93
+ retryOptions RetryOptions
86
94
87
95
// listener is the single listener for the token manager.
88
96
// It is used to receive updates from the token manager.
@@ -96,17 +104,17 @@ type entraidTokenManager struct {
96
104
}
97
105
98
106
func (e * entraidTokenManager ) GetToken () (* Token , error ) {
99
- if e .token != nil && e .token .ExpiresAt <= time .Now ().Unix ( ) {
107
+ if e .token != nil && e .token .ExpiresOn . After ( time .Now ().Add ( MinTokenTTL ) ) {
100
108
// copy the token so the caller can't modify it
101
109
return copyToken (e .token ), nil
102
110
}
103
111
104
- rawToken , err := e .idp .RequestToken ()
112
+ rawToken , expiresOn , err := e .idp .RequestToken ()
105
113
if err != nil {
106
114
return nil , fmt .Errorf ("failed to request token: %w" , err )
107
115
}
108
116
109
- token , err := e .TokenParser (rawToken )
117
+ token , err := e .tokenParser (rawToken , expiresOn )
110
118
if err != nil {
111
119
return nil , fmt .Errorf ("failed to parse token: %w" , err )
112
120
}
@@ -148,10 +156,53 @@ func (e *entraidTokenManager) Start(listener TokenListener) (cancelFunc, error)
148
156
149
157
go listener .OnTokenNext (token )
150
158
159
+ go func (listener TokenListener ) {
160
+ // Simulate token refresh
161
+ for {
162
+ time .Sleep (
163
+ time .Duration (e .retryOptions .InitialDelayMs ) * time .Millisecond )
164
+ newToken , err := e .GetToken ()
165
+ if err != nil {
166
+ listener .OnTokenError (err )
167
+ return
168
+ }
169
+ listener .OnTokenNext (newToken )
170
+ }
171
+ }(e .listener )
151
172
cancel := func () error {
152
173
// Stop the token manager.
153
174
return nil
154
175
}
155
176
156
177
return cancel , nil
157
178
}
179
+
180
+ // defaultRetryOptionsOr returns the default retry options if the provided options are not set.
181
+ // It sets the maximum number of attempts, initial delay, maximum delay, and backoff multiplier.
182
+ // The default values are 3 attempts, 1000 ms initial delay, 10000 ms maximum delay, and 2.0 backoff multiplier.
183
+ // The values can be overridden by the user.
184
+ func defaultRetryOptionsOr (retryOptions RetryOptions ) RetryOptions {
185
+ if retryOptions .MaxAttempts <= 0 {
186
+ retryOptions .MaxAttempts = 3
187
+ }
188
+ if retryOptions .InitialDelayMs == 0 {
189
+ retryOptions .InitialDelayMs = 1000
190
+ }
191
+ if retryOptions .BackoffMultiplier == 0 {
192
+ retryOptions .BackoffMultiplier = 2.0
193
+ }
194
+ if retryOptions .MaxDelayMs == 0 {
195
+ retryOptions .MaxDelayMs = 10000
196
+ }
197
+ return retryOptions
198
+ }
199
+
200
+ // defaultTokenParserOr returns the default token parser if the provided token parser is not set.
201
+ // It sets the default token parser to the defaultTokenParser function.
202
+ // The default token parser is used to parse the raw token and return a Token object.
203
+ func defaultTokenParserOr (tokenParser TokenParserFunc ) TokenParserFunc {
204
+ if tokenParser == nil {
205
+ return defaultTokenParser
206
+ }
207
+ return tokenParser
208
+ }
0 commit comments