72 lines
1.8 KiB
Go
72 lines
1.8 KiB
Go
|
package authcache
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
|
||
|
"github.com/go-logr/logr"
|
||
|
"golang.org/x/oauth2"
|
||
|
)
|
||
|
|
||
|
type cacheTokenSource struct {
|
||
|
cache Cache
|
||
|
|
||
|
tokenSource oauth2.TokenSource
|
||
|
ctx context.Context
|
||
|
}
|
||
|
|
||
|
func NewCacheTokenSource(ctx context.Context, cache Cache, tokenSource oauth2.TokenSource) oauth2.TokenSource {
|
||
|
// Avoid dupe wrapping
|
||
|
if rts, ok := tokenSource.(*cacheTokenSource); ok {
|
||
|
return rts
|
||
|
}
|
||
|
|
||
|
return &cacheTokenSource{
|
||
|
cache: cache,
|
||
|
tokenSource: tokenSource,
|
||
|
ctx: ctx,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (ts *cacheTokenSource) Token() (*oauth2.Token, error) {
|
||
|
log := logr.FromContextOrDiscard(ts.ctx).WithName("cacheTokenSource")
|
||
|
|
||
|
token, err := ts.cache.Fetch()
|
||
|
if err != nil {
|
||
|
log.V(1).Info("Failed to fetch token", "err", err.Error())
|
||
|
return nil, err
|
||
|
}
|
||
|
oldToken := token
|
||
|
|
||
|
// Do we have a cached token?
|
||
|
if token == nil || token.RefreshToken == "" {
|
||
|
// We are starting fresh
|
||
|
log.V(1).Info("No existing token, requesting fresh one")
|
||
|
newToken, err := ts.tokenSource.Token()
|
||
|
if err != nil {
|
||
|
log.V(1).Info("Failed to request fresh token", "err", err.Error())
|
||
|
return nil, err
|
||
|
}
|
||
|
token = newToken
|
||
|
} else if !token.Valid() /*|| token.Expiry.Add(-5*time.Minute).Before(time.Now())*/ {
|
||
|
// Our existing token has expired, refresh
|
||
|
log.V(1).Info("Existing token has expired or is about to expire, requesting refresh")
|
||
|
newToken, err := ts.tokenSource.Token()
|
||
|
if err != nil {
|
||
|
log.V(1).Info("Failed to refresh token", "err", err.Error())
|
||
|
return nil, err
|
||
|
}
|
||
|
token = newToken
|
||
|
}
|
||
|
|
||
|
// Persist token if changed/fresh
|
||
|
if oldToken == nil || oldToken.AccessToken != token.AccessToken {
|
||
|
log.V(1).Info("Persisting new token")
|
||
|
if err := ts.cache.Persist(token); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
log.V(1).Info("Returning token")
|
||
|
return token, nil
|
||
|
}
|