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 }