pomerium/internal/identity/oidc/refresh.go
Kenneth Jenkins 39a477c510
identity: override TokenSource expiry behavior (#4632)
The current session refresh loop attempts to refresh access tokens when
they are due to expire in less than one minute. However, the code to
perform the refresh relies on a TokenSource from the x/oauth2 package,
which has its own internal 'expiryDelta' threshold, with a default of
10 seconds. As a result, the first four or five attempts to refresh a
particular access token will not actually refresh the token. The refresh
will happen only when the access token is within 10 seconds of expiring.

Instead, before we obtain a new TokenSource, first clear any existing
access token. This causes the TokenSource to consider the token invalid,
triggering a refresh. This should give the refresh loop more control
over when refreshes happen.

Consolidate this logic in a new Refresh() method in the oidc package.
Add unit tests for this new method.
2023-10-23 08:20:04 -07:00

29 lines
824 B
Go

package oidc
import (
"context"
"fmt"
"golang.org/x/oauth2"
)
// Refresh requests a new oauth2.Token based on an existing Token and the
// provided Config. The existing Token must contain a refresh token.
func Refresh(ctx context.Context, cfg *oauth2.Config, t *oauth2.Token) (*oauth2.Token, error) {
if t == nil || t.RefreshToken == "" {
return nil, ErrMissingRefreshToken
}
// Note: the TokenSource returned by oauth2.Config has its own threshold
// for determining when to attempt a refresh. In order to force a refresh
// we can remove the current AccessToken.
t = &oauth2.Token{
TokenType: t.TokenType,
RefreshToken: t.RefreshToken,
}
newToken, err := cfg.TokenSource(ctx, t).Token()
if err != nil {
return nil, fmt.Errorf("identity/oidc: refresh failed: %w", err)
}
return newToken, nil
}