@@ -32,7 +32,8 @@ const (
3232 tokenAPI = "https://service-account.api.stackit.cloud/token" //nolint:gosec // linter false positive
3333 defaultTokenType = "Bearer"
3434 defaultScope = ""
35- tokenExpirationLeeway = time .Second * 5
35+
36+ defaultTokenExpirationLeeway = time .Second * 5
3637)
3738
3839// KeyFlow handles auth with SA key
@@ -46,6 +47,10 @@ type KeyFlow struct {
4647
4748 tokenMutex sync.RWMutex
4849 token * TokenResponseBody
50+
51+ // If the current access token would expire in less than TokenExpirationLeeway,
52+ // the client will refresh it early to prevent clock skew or other timing issues.
53+ tokenExpirationLeeway time.Duration
4954}
5055
5156// KeyFlowConfig is the flow config
@@ -130,6 +135,8 @@ func (c *KeyFlow) Init(cfg *KeyFlowConfig) error {
130135 c .config .TokenUrl = tokenAPI
131136 }
132137
138+ c .tokenExpirationLeeway = defaultTokenExpirationLeeway
139+
133140 if c .rt = cfg .HTTPTransport ; c .rt == nil {
134141 c .rt = http .DefaultTransport
135142 }
@@ -205,7 +212,7 @@ func (c *KeyFlow) GetAccessToken() (string, error) {
205212 }
206213 c .tokenMutex .RUnlock ()
207214
208- accessTokenExpired , err := tokenExpired (accessToken )
215+ accessTokenExpired , err := tokenExpired (accessToken , c . tokenExpirationLeeway )
209216 if err != nil {
210217 return "" , fmt .Errorf ("check access token is expired: %w" , err )
211218 }
@@ -253,6 +260,10 @@ func (c *KeyFlow) validate() error {
253260 }
254261 c .privateKeyPEM = pem .EncodeToMemory (privKeyPEM )
255262
263+ if c .tokenExpirationLeeway < 0 {
264+ return fmt .Errorf ("token expiration leeway cannot be negative" )
265+ }
266+
256267 return nil
257268}
258269
@@ -269,7 +280,7 @@ func (c *KeyFlow) recreateAccessToken() error {
269280 }
270281 c .tokenMutex .RUnlock ()
271282
272- refreshTokenExpired , err := tokenExpired (refreshToken )
283+ refreshTokenExpired , err := tokenExpired (refreshToken , c . tokenExpirationLeeway )
273284 if err != nil {
274285 return err
275286 }
@@ -390,7 +401,7 @@ func (c *KeyFlow) parseTokenResponse(res *http.Response) error {
390401 return nil
391402}
392403
393- func tokenExpired (token string ) (bool , error ) {
404+ func tokenExpired (token string , tokenExpirationLeeway time. Duration ) (bool , error ) {
394405 if token == "" {
395406 return true , nil
396407 }
0 commit comments