diff --git a/sdk/azidentity/authorization_code_credential.go b/sdk/azidentity/authorization_code_credential.go index 981f3dc5783b..05794c676dbd 100644 --- a/sdk/azidentity/authorization_code_credential.go +++ b/sdk/azidentity/authorization_code_credential.go @@ -80,7 +80,7 @@ func (c *AuthorizationCodeCredential) GetToken(ctx context.Context, opts azcore. // AuthenticationPolicy implements the azcore.Credential interface on AuthorizationCodeCredential. func (c *AuthorizationCodeCredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - return newBearerTokenPolicy(c, options) + return azcore.NewBearerTokenPolicy(c, options) } var _ azcore.TokenCredential = (*AuthorizationCodeCredential)(nil) diff --git a/sdk/azidentity/azure_cli_credential.go b/sdk/azidentity/azure_cli_credential.go index 4e4d0a78c42c..1ff9bc1f9e45 100644 --- a/sdk/azidentity/azure_cli_credential.go +++ b/sdk/azidentity/azure_cli_credential.go @@ -70,7 +70,7 @@ func (c *AzureCLICredential) GetToken(ctx context.Context, opts azcore.TokenRequ // AuthenticationPolicy implements the azcore.Credential interface on AzureCLICredential. func (c *AzureCLICredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - return newBearerTokenPolicy(c, options) + return azcore.NewBearerTokenPolicy(c, options) } const timeoutCLIRequest = 10000 * time.Millisecond diff --git a/sdk/azidentity/bearer_token_policy.go b/sdk/azidentity/bearer_token_policy.go deleted file mode 100644 index d330afe98cc6..000000000000 --- a/sdk/azidentity/bearer_token_policy.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package azidentity - -import ( - "net/http" - "sync" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" -) - -const ( - bearerTokenPrefix = "Bearer " -) - -type bearerTokenPolicy struct { - // cond is used to synchronize token refresh. the locker - // must be locked when updating the following shared state. - cond *sync.Cond - - // renewing indicates that the token is in the process of being refreshed - renewing bool - - // header contains the authorization header value - header string - - // expiresOn is when the token will expire - expiresOn time.Time - - // the following fields are read-only - creds azcore.TokenCredential - options azcore.TokenRequestOptions -} - -func newBearerTokenPolicy(creds azcore.TokenCredential, opts azcore.AuthenticationPolicyOptions) *bearerTokenPolicy { - return &bearerTokenPolicy{ - cond: sync.NewCond(&sync.Mutex{}), - creds: creds, - options: opts.Options, - } -} - -func (b *bearerTokenPolicy) Do(req *azcore.Request) (*azcore.Response, error) { - if req.URL.Scheme != "https" { - // HTTPS must be used, otherwise the tokens are at the risk of being exposed - return nil, &AuthenticationFailedError{msg: "token credentials require a URL using the HTTPS protocol scheme"} - } - // create a "refresh window" before the token's real expiration date. - // this allows callers to continue to use the old token while the - // refresh is in progress. - const window = 2 * time.Minute - now, getToken, header := time.Now(), false, "" - // acquire exclusive lock - b.cond.L.Lock() - for { - if b.expiresOn.IsZero() || b.expiresOn.Before(now) { - // token was never obtained or has expired - if !b.renewing { - // another go routine isn't refreshing the token so this one will - b.renewing = true - getToken = true - break - } - // getting here means this go routine will wait for the token to refresh - } else if b.expiresOn.Add(-window).Before(now) { - // token is within the expiration window - if !b.renewing { - // another go routine isn't refreshing the token so this one will - b.renewing = true - getToken = true - break - } - // this go routine will use the existing token while another refreshes it - header = b.header - break - } else { - // token is not expiring yet so use it as-is - header = b.header - break - } - // wait for the token to refresh - b.cond.Wait() - } - b.cond.L.Unlock() - if getToken { - // this go routine has been elected to refresh the token - tk, err := b.creds.GetToken(req.Context(), b.options) - // update shared state - b.cond.L.Lock() - // to avoid a deadlock if GetToken() fails we MUST reset b.renewing to false before returning - b.renewing = false - if err != nil { - b.unlock() - return nil, err - } - header = bearerTokenPrefix + tk.Token - b.header = header - b.expiresOn = tk.ExpiresOn - b.unlock() - } - req.Request.Header.Set(azcore.HeaderXmsDate, time.Now().UTC().Format(http.TimeFormat)) - req.Request.Header.Set(azcore.HeaderAuthorization, header) - return req.Next() -} - -// signal any waiters that the token has been refreshed -func (b *bearerTokenPolicy) unlock() { - b.cond.Broadcast() - b.cond.L.Unlock() -} diff --git a/sdk/azidentity/chained_token_credential.go b/sdk/azidentity/chained_token_credential.go index af06decfd221..3cd789a80530 100644 --- a/sdk/azidentity/chained_token_credential.go +++ b/sdk/azidentity/chained_token_credential.go @@ -70,7 +70,7 @@ func (c *ChainedTokenCredential) GetToken(ctx context.Context, opts azcore.Token // AuthenticationPolicy implements the azcore.Credential interface on ChainedTokenCredential and sets the bearer token func (c *ChainedTokenCredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - return newBearerTokenPolicy(c, options) + return azcore.NewBearerTokenPolicy(c, options) } // helper function used to chain the error messages of the CredentialUnavailableError slice diff --git a/sdk/azidentity/client_certificate_credential.go b/sdk/azidentity/client_certificate_credential.go index edb92471edd3..7e4dfd73190b 100644 --- a/sdk/azidentity/client_certificate_credential.go +++ b/sdk/azidentity/client_certificate_credential.go @@ -218,5 +218,5 @@ func (c *ClientCertificateCredential) GetToken(ctx context.Context, opts azcore. // AuthenticationPolicy implements the azcore.Credential interface on ClientCertificateCredential. func (c *ClientCertificateCredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - return newBearerTokenPolicy(c, options) + return azcore.NewBearerTokenPolicy(c, options) } diff --git a/sdk/azidentity/client_secret_credential.go b/sdk/azidentity/client_secret_credential.go index 6cc0770e3465..b5e1102aba32 100644 --- a/sdk/azidentity/client_secret_credential.go +++ b/sdk/azidentity/client_secret_credential.go @@ -76,7 +76,7 @@ func (c *ClientSecretCredential) GetToken(ctx context.Context, opts azcore.Token // AuthenticationPolicy implements the azcore.Credential interface on ClientSecretCredential and calls the Bearer Token policy // to get the bearer token. func (c *ClientSecretCredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - return newBearerTokenPolicy(c, options) + return azcore.NewBearerTokenPolicy(c, options) } var _ azcore.TokenCredential = (*ClientSecretCredential)(nil) diff --git a/sdk/azidentity/device_code_credential.go b/sdk/azidentity/device_code_credential.go index 55b716622388..4852fed17044 100644 --- a/sdk/azidentity/device_code_credential.go +++ b/sdk/azidentity/device_code_credential.go @@ -169,7 +169,7 @@ func (c *DeviceCodeCredential) GetToken(ctx context.Context, opts azcore.TokenRe // AuthenticationPolicy implements the azcore.Credential interface on DeviceCodeCredential. func (c *DeviceCodeCredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - return newBearerTokenPolicy(c, options) + return azcore.NewBearerTokenPolicy(c, options) } // deviceCodeResult is used to store device code related information to help the user login and allow the device code flow to continue diff --git a/sdk/azidentity/environment_credential.go b/sdk/azidentity/environment_credential.go index 811277bd5056..28275bdd9412 100644 --- a/sdk/azidentity/environment_credential.go +++ b/sdk/azidentity/environment_credential.go @@ -101,7 +101,7 @@ func (c *EnvironmentCredential) GetToken(ctx context.Context, opts azcore.TokenR // AuthenticationPolicy implements the azcore.Credential interface on EnvironmentCredential. func (c *EnvironmentCredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - return newBearerTokenPolicy(c.cred, options) + return azcore.NewBearerTokenPolicy(c.cred, options) } var _ azcore.TokenCredential = (*EnvironmentCredential)(nil) diff --git a/sdk/azidentity/interactive_browser_credential.go b/sdk/azidentity/interactive_browser_credential.go index 3b24888b18b6..6892576c92a4 100644 --- a/sdk/azidentity/interactive_browser_credential.go +++ b/sdk/azidentity/interactive_browser_credential.go @@ -104,7 +104,7 @@ func (c *InteractiveBrowserCredential) GetToken(ctx context.Context, opts azcore // AuthenticationPolicy implements the azcore.Credential interface on InteractiveBrowserCredential. func (c *InteractiveBrowserCredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - return newBearerTokenPolicy(c, options) + return azcore.NewBearerTokenPolicy(c, options) } var _ azcore.TokenCredential = (*InteractiveBrowserCredential)(nil) diff --git a/sdk/azidentity/managed_identity_credential.go b/sdk/azidentity/managed_identity_credential.go index 48880536dc31..07941435628b 100644 --- a/sdk/azidentity/managed_identity_credential.go +++ b/sdk/azidentity/managed_identity_credential.go @@ -106,5 +106,5 @@ func (c *ManagedIdentityCredential) GetToken(ctx context.Context, opts azcore.To // AuthenticationPolicy implements the azcore.Credential interface on ManagedIdentityCredential. // NOTE: The TokenRequestOptions included in AuthenticationPolicyOptions must be a slice of resources in this case and not scopes. func (c *ManagedIdentityCredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - return newBearerTokenPolicy(c, options) + return azcore.NewBearerTokenPolicy(c, options) } diff --git a/sdk/azidentity/username_password_credential.go b/sdk/azidentity/username_password_credential.go index c77d96833b20..4627473e7067 100644 --- a/sdk/azidentity/username_password_credential.go +++ b/sdk/azidentity/username_password_credential.go @@ -79,5 +79,5 @@ func (c *UsernamePasswordCredential) GetToken(ctx context.Context, opts azcore.T // AuthenticationPolicy implements the azcore.Credential interface on UsernamePasswordCredential. func (c *UsernamePasswordCredential) AuthenticationPolicy(options azcore.AuthenticationPolicyOptions) azcore.Policy { - return newBearerTokenPolicy(c, options) + return azcore.NewBearerTokenPolicy(c, options) }