Skip to content

Commit 4d8ea71

Browse files
committed
wip
1 parent ca920c5 commit 4d8ea71

File tree

3 files changed

+80
-21
lines changed

3 files changed

+80
-21
lines changed

identity_provider.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
package entraid
22

3+
import "time"
4+
5+
// IdentityProvider is an interface that defines the methods for an identity provider.
6+
// It is used to request a token for authentication.
7+
// The identity provider is responsible for providing the raw authentication token.
38
type IdentityProvider interface {
49
// RequestToken requests a token from the identity provider.
5-
RequestToken() (string, error)
10+
// It returns the token, the expiration time, and an error if any.
11+
RequestToken() (string, time.Time, error)
612
}

token.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package entraid
22

3+
import "time"
4+
35
// Token represents the authentication token used to access the Entraid API.
46
// It contains the username, password, expiration time, time to live, and the raw token.
57
// The token is used to authenticate the user and authorize access to the API.
@@ -10,23 +12,23 @@ type Token struct {
1012
Username string `json:"username"`
1113
// Password is the password of the user.
1214
Password string `json:"password"`
13-
// ExpiresAt is the expiration time of the token.
14-
ExpiresAt int64 `json:"expires_at"`
15+
// ExpiresOn is the expiration time of the token.
16+
ExpiresOn time.Time `json:"expires_on"`
1517
// TTL is the time to live of the token.
1618
TTL int64 `json:"ttl"`
1719
// RawToken is the authentication token.
1820
RawToken string `json:"raw_token"`
1921
}
2022

2123
// TokenParserFunc is a function that parses the token and returns the username and password.
22-
type TokenParserFunc func(token string) (*Token, error)
24+
type TokenParserFunc func(token string, expiresOn time.Time) (*Token, error)
2325

2426
// copyToken creates a copy of the token.
2527
func copyToken(token *Token) *Token {
2628
return &Token{
2729
Username: token.Username,
2830
Password: token.Password,
29-
ExpiresAt: token.ExpiresAt,
31+
ExpiresOn: token.ExpiresOn,
3032
TTL: token.TTL,
3133
RawToken: token.RawToken,
3234
}

token_manager.go

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"time"
77
)
88

9+
const MinTokenTTL = 30 * time.Minute
10+
911
// TokenManagerOptions is a struct that contains the options for the TokenManager.
1012
type TokenManagerOptions struct {
1113
// ExpirationRefreshRatio is the ratio of the token expiration time to refresh the token.
@@ -15,10 +17,10 @@ type TokenManagerOptions struct {
1517
// the token will be refreshed after 30 minutes.
1618
ExpirationRefreshRatio float64
1719

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.
1921
// The function takes the raw token as a string and returns a Token object and an error.
2022
// If this function is not provided, the default implementation will be used.
21-
ParseToken TokenParserFunc
23+
TokenParser TokenParserFunc
2224

2325
// RetryOptions is a struct that contains the options for retrying the token request.
2426
// It contains the maximum number of attempts, initial delay, maximum delay, and backoff multiplier.
@@ -49,14 +51,14 @@ type TokenManager interface {
4951
}
5052

5153
// 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) {
5355
// Parse the token and return the username and password.
5456
// This is a placeholder implementation.
5557
return &Token{
5658
Username: "username",
5759
Password: "password",
58-
ExpiresAt: time.Now().Add(1 * time.Hour).Unix(),
59-
TTL: 3600,
60+
ExpiresOn: expiresOn,
61+
TTL: expiresOn.Unix() - time.Now().Unix(),
6062
RawToken: rawToken,
6163
}, nil
6264
}
@@ -66,14 +68,14 @@ var defaultTokenParser = func(rawToken string) (*Token, error) {
6668
// The IdentityProvider is used to obtain the token, and the TokenManagerOptions contains options for the TokenManager.
6769
// The TokenManager is responsible for managing the token and refreshing it when necessary.
6870
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+
7374
return &entraidTokenManager{
74-
idp: idp,
75-
token: nil,
76-
TokenParser: tokenParser,
75+
idp: idp,
76+
token: nil,
77+
tokenParser: tokenParser,
78+
retryOptions: retryOptions,
7779
}
7880
}
7981

@@ -82,7 +84,13 @@ type entraidTokenManager struct {
8284
idp IdentityProvider
8385
token *Token
8486
// 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
8694

8795
// listener is the single listener for the token manager.
8896
// It is used to receive updates from the token manager.
@@ -96,17 +104,17 @@ type entraidTokenManager struct {
96104
}
97105

98106
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)) {
100108
// copy the token so the caller can't modify it
101109
return copyToken(e.token), nil
102110
}
103111

104-
rawToken, err := e.idp.RequestToken()
112+
rawToken, expiresOn, err := e.idp.RequestToken()
105113
if err != nil {
106114
return nil, fmt.Errorf("failed to request token: %w", err)
107115
}
108116

109-
token, err := e.TokenParser(rawToken)
117+
token, err := e.tokenParser(rawToken, expiresOn)
110118
if err != nil {
111119
return nil, fmt.Errorf("failed to parse token: %w", err)
112120
}
@@ -148,10 +156,53 @@ func (e *entraidTokenManager) Start(listener TokenListener) (cancelFunc, error)
148156

149157
go listener.OnTokenNext(token)
150158

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)
151172
cancel := func() error {
152173
// Stop the token manager.
153174
return nil
154175
}
155176

156177
return cancel, nil
157178
}
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

Comments
 (0)