diff --git a/pkg/auth/oidc.go b/pkg/auth/oidc.go index 259ff878..207b1ea5 100644 --- a/pkg/auth/oidc.go +++ b/pkg/auth/oidc.go @@ -17,6 +17,7 @@ package auth import ( "context" "fmt" + "github.com/fatedier/frp/pkg/util/xlog" "time" "github.com/coreos/go-oidc/v3/oidc" @@ -31,6 +32,8 @@ type OidcAuthProvider struct { additionalAuthScopes []v1.AuthScope tokenGenerator *clientcredentials.Config + + retryConfig v1.AuthRetryConfig } func NewOidcAuthSetter(additionalAuthScopes []v1.AuthScope, cfg v1.AuthOIDCClientConfig) *OidcAuthProvider { @@ -54,16 +57,19 @@ func NewOidcAuthSetter(additionalAuthScopes []v1.AuthScope, cfg v1.AuthOIDCClien return &OidcAuthProvider{ additionalAuthScopes: additionalAuthScopes, tokenGenerator: tokenGenerator, + retryConfig: cfg.AuthRetryConfig, } } -func withRetries(retries int, fn func() (accessToken string, error error)) (accessToken string, err error) { - exponentialBackOff := time.Second * 1 +func withRetries(retries int, delay time.Duration, fn func() (accessToken string, error error)) (accessToken string, err error) { + xl := xlog.FromContextSafe(context.Background()) + exponentialBackOff := time.Second * delay for i := 0; i < retries; i++ { accessToken, err = fn() if err == nil { return accessToken, nil } + xl.Warn("Failed to generate OIDC token for login: %v. Retrying %i more times", err, retries-i) time.Sleep(exponentialBackOff) exponentialBackOff *= 2 } @@ -71,7 +77,7 @@ func withRetries(retries int, fn func() (accessToken string, error error)) (acce } func (auth *OidcAuthProvider) generateAccessToken() (accessToken string, err error) { - return withRetries(10, func() (accessToken string, error error) { + return withRetries(auth.retryConfig.MaxRetries, auth.retryConfig.RetryDelay, func() (accessToken string, error error) { tokenObj, err := auth.tokenGenerator.Token(context.Background()) if err != nil { return "", fmt.Errorf("couldn't generate OIDC token for login: %v", err) diff --git a/pkg/config/v1/client.go b/pkg/config/v1/client.go index 9029aa73..835f4030 100644 --- a/pkg/config/v1/client.go +++ b/pkg/config/v1/client.go @@ -38,6 +38,9 @@ type ClientCommonConfig struct { // changed to "{user}.{proxy_name}". User string `json:"user,omitempty"` + // AuthRetryConfig specifies the retry strategy for retrieving access tokens. + AuthRetryConfig AuthRetryConfig `json:"authRetry,omitempty"` + // ServerAddr specifies the address of the server to connect to. By // default, this value is "0.0.0.0". ServerAddr string `json:"serverAddr,omitempty"` @@ -197,4 +200,6 @@ type AuthOIDCClientConfig struct { // AdditionalEndpointParams specifies additional parameters to be sent // this field will be transfer to map[string][]string in OIDC token generator. AdditionalEndpointParams map[string]string `json:"additionalEndpointParams,omitempty"` + // AuthRetryConfig specifies the retry strategy for retrieving access tokens. + AuthRetryConfig AuthRetryConfig `json:"authRetry,omitempty"` } diff --git a/pkg/config/v1/common.go b/pkg/config/v1/common.go index 422a8082..ada0a3ad 100644 --- a/pkg/config/v1/common.go +++ b/pkg/config/v1/common.go @@ -16,6 +16,7 @@ package v1 import ( "github.com/fatedier/frp/pkg/util/util" + "time" ) type AuthScope string @@ -115,3 +116,12 @@ type HTTPPluginOptions struct { type HeaderOperations struct { Set map[string]string `json:"set,omitempty"` } + +type AuthRetryConfig struct { + // MaxRetries specifies the maximum number of retries to authenticate + // with frps. By default, this value is 0. + MaxRetries int `json:"maxRetries,omitempty"` + // RetryDelay specifies the delay between retries to authenticate with + // frps, in seconds. By default, this value is 1. + RetryDelay time.Duration `json:"retryDelay,omitempty"` +}