aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>2023-10-09 01:56:22 +0000
committerAleksandr Nogikh <nogikh@google.com>2023-10-09 11:19:56 +0000
commit3c53c7d911d9dfb0bb846955a4644746fcc442d9 (patch)
tree98b80c251bff9e1f08debfec09adaaac765e737c
parentf3a9f5507f0811a5678eec8e7da3618ce3890d32 (diff)
mod: do: bump golang.org/x/oauth2 from 0.12.0 to 0.13.0
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.12.0 to 0.13.0. - [Commits](https://github.com/golang/oauth2/compare/v0.12.0...v0.13.0) --- updated-dependencies: - dependency-name: golang.org/x/oauth2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
-rw-r--r--go.mod2
-rw-r--r--go.sum4
-rw-r--r--vendor/golang.org/x/oauth2/deviceauth.go198
-rw-r--r--vendor/golang.org/x/oauth2/google/default.go31
-rw-r--r--vendor/golang.org/x/oauth2/google/google.go46
-rw-r--r--vendor/golang.org/x/oauth2/google/internal/externalaccount/aws.go47
-rw-r--r--vendor/golang.org/x/oauth2/google/internal/externalaccount/basecredentials.go45
-rw-r--r--vendor/golang.org/x/oauth2/google/internal/externalaccount/executablecredsource.go4
-rw-r--r--vendor/golang.org/x/oauth2/google/internal/externalaccount/filecredsource.go4
-rw-r--r--vendor/golang.org/x/oauth2/google/internal/externalaccount/header.go64
-rw-r--r--vendor/golang.org/x/oauth2/google/internal/externalaccount/urlcredsource.go4
-rw-r--r--vendor/golang.org/x/oauth2/google/internal/externalaccountauthorizeduser/externalaccountauthorizeduser.go114
-rw-r--r--vendor/golang.org/x/oauth2/google/internal/stsexchange/clientauth.go (renamed from vendor/golang.org/x/oauth2/google/internal/externalaccount/clientauth.go)8
-rw-r--r--vendor/golang.org/x/oauth2/google/internal/stsexchange/sts_exchange.go (renamed from vendor/golang.org/x/oauth2/google/internal/externalaccount/sts_exchange.go)42
-rw-r--r--vendor/golang.org/x/oauth2/oauth2.go29
-rw-r--r--vendor/golang.org/x/oauth2/pkce.go68
-rw-r--r--vendor/modules.txt4
17 files changed, 592 insertions, 122 deletions
diff --git a/go.mod b/go.mod
index 96c7091b1..1195d2c79 100644
--- a/go.mod
+++ b/go.mod
@@ -17,7 +17,7 @@ require (
github.com/stretchr/testify v1.8.4
github.com/ulikunitz/xz v0.5.11
golang.org/x/net v0.16.0
- golang.org/x/oauth2 v0.12.0
+ golang.org/x/oauth2 v0.13.0
golang.org/x/perf v0.0.0-20230221235046-aebcfb61e84c
golang.org/x/sync v0.4.0
golang.org/x/sys v0.13.0
diff --git a/go.sum b/go.sum
index 40769263c..116064524 100644
--- a/go.sum
+++ b/go.sum
@@ -787,8 +787,8 @@ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
-golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
+golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY=
+golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
golang.org/x/perf v0.0.0-20230221235046-aebcfb61e84c h1:xR7iBj/IHpQuWFrftdwa1ttoVJKSDg+37NHA2XblmrU=
golang.org/x/perf v0.0.0-20230221235046-aebcfb61e84c/go.mod h1:UBKtEnL8aqnd+0JHqZ+2qoMDwtuy6cYhhKNoHLBiTQc=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
diff --git a/vendor/golang.org/x/oauth2/deviceauth.go b/vendor/golang.org/x/oauth2/deviceauth.go
new file mode 100644
index 000000000..e99c92f39
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/deviceauth.go
@@ -0,0 +1,198 @@
+package oauth2
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "strings"
+ "time"
+
+ "golang.org/x/oauth2/internal"
+)
+
+// https://datatracker.ietf.org/doc/html/rfc8628#section-3.5
+const (
+ errAuthorizationPending = "authorization_pending"
+ errSlowDown = "slow_down"
+ errAccessDenied = "access_denied"
+ errExpiredToken = "expired_token"
+)
+
+// DeviceAuthResponse describes a successful RFC 8628 Device Authorization Response
+// https://datatracker.ietf.org/doc/html/rfc8628#section-3.2
+type DeviceAuthResponse struct {
+ // DeviceCode
+ DeviceCode string `json:"device_code"`
+ // UserCode is the code the user should enter at the verification uri
+ UserCode string `json:"user_code"`
+ // VerificationURI is where user should enter the user code
+ VerificationURI string `json:"verification_uri"`
+ // VerificationURIComplete (if populated) includes the user code in the verification URI. This is typically shown to the user in non-textual form, such as a QR code.
+ VerificationURIComplete string `json:"verification_uri_complete,omitempty"`
+ // Expiry is when the device code and user code expire
+ Expiry time.Time `json:"expires_in,omitempty"`
+ // Interval is the duration in seconds that Poll should wait between requests
+ Interval int64 `json:"interval,omitempty"`
+}
+
+func (d DeviceAuthResponse) MarshalJSON() ([]byte, error) {
+ type Alias DeviceAuthResponse
+ var expiresIn int64
+ if !d.Expiry.IsZero() {
+ expiresIn = int64(time.Until(d.Expiry).Seconds())
+ }
+ return json.Marshal(&struct {
+ ExpiresIn int64 `json:"expires_in,omitempty"`
+ *Alias
+ }{
+ ExpiresIn: expiresIn,
+ Alias: (*Alias)(&d),
+ })
+
+}
+
+func (c *DeviceAuthResponse) UnmarshalJSON(data []byte) error {
+ type Alias DeviceAuthResponse
+ aux := &struct {
+ ExpiresIn int64 `json:"expires_in"`
+ // workaround misspelling of verification_uri
+ VerificationURL string `json:"verification_url"`
+ *Alias
+ }{
+ Alias: (*Alias)(c),
+ }
+ if err := json.Unmarshal(data, &aux); err != nil {
+ return err
+ }
+ if aux.ExpiresIn != 0 {
+ c.Expiry = time.Now().UTC().Add(time.Second * time.Duration(aux.ExpiresIn))
+ }
+ if c.VerificationURI == "" {
+ c.VerificationURI = aux.VerificationURL
+ }
+ return nil
+}
+
+// DeviceAuth returns a device auth struct which contains a device code
+// and authorization information provided for users to enter on another device.
+func (c *Config) DeviceAuth(ctx context.Context, opts ...AuthCodeOption) (*DeviceAuthResponse, error) {
+ // https://datatracker.ietf.org/doc/html/rfc8628#section-3.1
+ v := url.Values{
+ "client_id": {c.ClientID},
+ }
+ if len(c.Scopes) > 0 {
+ v.Set("scope", strings.Join(c.Scopes, " "))
+ }
+ for _, opt := range opts {
+ opt.setValue(v)
+ }
+ return retrieveDeviceAuth(ctx, c, v)
+}
+
+func retrieveDeviceAuth(ctx context.Context, c *Config, v url.Values) (*DeviceAuthResponse, error) {
+ if c.Endpoint.DeviceAuthURL == "" {
+ return nil, errors.New("endpoint missing DeviceAuthURL")
+ }
+
+ req, err := http.NewRequest("POST", c.Endpoint.DeviceAuthURL, strings.NewReader(v.Encode()))
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ req.Header.Set("Accept", "application/json")
+
+ t := time.Now()
+ r, err := internal.ContextClient(ctx).Do(req)
+ if err != nil {
+ return nil, err
+ }
+
+ body, err := io.ReadAll(io.LimitReader(r.Body, 1<<20))
+ if err != nil {
+ return nil, fmt.Errorf("oauth2: cannot auth device: %v", err)
+ }
+ if code := r.StatusCode; code < 200 || code > 299 {
+ return nil, &RetrieveError{
+ Response: r,
+ Body: body,
+ }
+ }
+
+ da := &DeviceAuthResponse{}
+ err = json.Unmarshal(body, &da)
+ if err != nil {
+ return nil, fmt.Errorf("unmarshal %s", err)
+ }
+
+ if !da.Expiry.IsZero() {
+ // Make a small adjustment to account for time taken by the request
+ da.Expiry = da.Expiry.Add(-time.Since(t))
+ }
+
+ return da, nil
+}
+
+// DeviceAccessToken polls the server to exchange a device code for a token.
+func (c *Config) DeviceAccessToken(ctx context.Context, da *DeviceAuthResponse, opts ...AuthCodeOption) (*Token, error) {
+ if !da.Expiry.IsZero() {
+ var cancel context.CancelFunc
+ ctx, cancel = context.WithDeadline(ctx, da.Expiry)
+ defer cancel()
+ }
+
+ // https://datatracker.ietf.org/doc/html/rfc8628#section-3.4
+ v := url.Values{
+ "client_id": {c.ClientID},
+ "grant_type": {"urn:ietf:params:oauth:grant-type:device_code"},
+ "device_code": {da.DeviceCode},
+ }
+ if len(c.Scopes) > 0 {
+ v.Set("scope", strings.Join(c.Scopes, " "))
+ }
+ for _, opt := range opts {
+ opt.setValue(v)
+ }
+
+ // "If no value is provided, clients MUST use 5 as the default."
+ // https://datatracker.ietf.org/doc/html/rfc8628#section-3.2
+ interval := da.Interval
+ if interval == 0 {
+ interval = 5
+ }
+
+ ticker := time.NewTicker(time.Duration(interval) * time.Second)
+ defer ticker.Stop()
+ for {
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ case <-ticker.C:
+ tok, err := retrieveToken(ctx, c, v)
+ if err == nil {
+ return tok, nil
+ }
+
+ e, ok := err.(*RetrieveError)
+ if !ok {
+ return nil, err
+ }
+ switch e.ErrorCode {
+ case errSlowDown:
+ // https://datatracker.ietf.org/doc/html/rfc8628#section-3.5
+ // "the interval MUST be increased by 5 seconds for this and all subsequent requests"
+ interval += 5
+ ticker.Reset(time.Duration(interval) * time.Second)
+ case errAuthorizationPending:
+ // Do nothing.
+ case errAccessDenied, errExpiredToken:
+ fallthrough
+ default:
+ return tok, err
+ }
+ }
+ }
+}
diff --git a/vendor/golang.org/x/oauth2/google/default.go b/vendor/golang.org/x/oauth2/google/default.go
index 2cf71f0f9..12b12a30c 100644
--- a/vendor/golang.org/x/oauth2/google/default.go
+++ b/vendor/golang.org/x/oauth2/google/default.go
@@ -19,7 +19,10 @@ import (
"golang.org/x/oauth2/authhandler"
)
-const adcSetupURL = "https://cloud.google.com/docs/authentication/external/set-up-adc"
+const (
+ adcSetupURL = "https://cloud.google.com/docs/authentication/external/set-up-adc"
+ universeDomainDefault = "googleapis.com"
+)
// Credentials holds Google credentials, including "Application Default Credentials".
// For more details, see:
@@ -37,6 +40,18 @@ type Credentials struct {
// environment and not with a credentials file, e.g. when code is
// running on Google Cloud Platform.
JSON []byte
+
+ // universeDomain is the default service domain for a given Cloud universe.
+ universeDomain string
+}
+
+// UniverseDomain returns the default service domain for a given Cloud universe.
+// The default value is "googleapis.com".
+func (c *Credentials) UniverseDomain() string {
+ if c.universeDomain == "" {
+ return universeDomainDefault
+ }
+ return c.universeDomain
}
// DefaultCredentials is the old name of Credentials.
@@ -200,15 +215,23 @@ func CredentialsFromJSONWithParams(ctx context.Context, jsonData []byte, params
if err := json.Unmarshal(jsonData, &f); err != nil {
return nil, err
}
+
+ universeDomain := f.UniverseDomain
+ // Authorized user credentials are only supported in the googleapis.com universe.
+ if f.Type == userCredentialsKey {
+ universeDomain = universeDomainDefault
+ }
+
ts, err := f.tokenSource(ctx, params)
if err != nil {
return nil, err
}
ts = newErrWrappingTokenSource(ts)
return &Credentials{
- ProjectID: f.ProjectID,
- TokenSource: ts,
- JSON: jsonData,
+ ProjectID: f.ProjectID,
+ TokenSource: ts,
+ JSON: jsonData,
+ universeDomain: universeDomain,
}, nil
}
diff --git a/vendor/golang.org/x/oauth2/google/google.go b/vendor/golang.org/x/oauth2/google/google.go
index cc1223889..c66c53527 100644
--- a/vendor/golang.org/x/oauth2/google/google.go
+++ b/vendor/golang.org/x/oauth2/google/google.go
@@ -16,14 +16,16 @@ import (
"cloud.google.com/go/compute/metadata"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google/internal/externalaccount"
+ "golang.org/x/oauth2/google/internal/externalaccountauthorizeduser"
"golang.org/x/oauth2/jwt"
)
// Endpoint is Google's OAuth 2.0 default endpoint.
var Endpoint = oauth2.Endpoint{
- AuthURL: "https://accounts.google.com/o/oauth2/auth",
- TokenURL: "https://oauth2.googleapis.com/token",
- AuthStyle: oauth2.AuthStyleInParams,
+ AuthURL: "https://accounts.google.com/o/oauth2/auth",
+ TokenURL: "https://oauth2.googleapis.com/token",
+ DeviceAuthURL: "https://oauth2.googleapis.com/device/code",
+ AuthStyle: oauth2.AuthStyleInParams,
}
// MTLSTokenURL is Google's OAuth 2.0 default mTLS endpoint.
@@ -95,10 +97,11 @@ func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, error) {
// JSON key file types.
const (
- serviceAccountKey = "service_account"
- userCredentialsKey = "authorized_user"
- externalAccountKey = "external_account"
- impersonatedServiceAccount = "impersonated_service_account"
+ serviceAccountKey = "service_account"
+ userCredentialsKey = "authorized_user"
+ externalAccountKey = "external_account"
+ externalAccountAuthorizedUserKey = "external_account_authorized_user"
+ impersonatedServiceAccount = "impersonated_service_account"
)
// credentialsFile is the unmarshalled representation of a credentials file.
@@ -106,12 +109,13 @@ type credentialsFile struct {
Type string `json:"type"`
// Service Account fields
- ClientEmail string `json:"client_email"`
- PrivateKeyID string `json:"private_key_id"`
- PrivateKey string `json:"private_key"`
- AuthURL string `json:"auth_uri"`
- TokenURL string `json:"token_uri"`
- ProjectID string `json:"project_id"`
+ ClientEmail string `json:"client_email"`
+ PrivateKeyID string `json:"private_key_id"`
+ PrivateKey string `json:"private_key"`
+ AuthURL string `json:"auth_uri"`
+ TokenURL string `json:"token_uri"`
+ ProjectID string `json:"project_id"`
+ UniverseDomain string `json:"universe_domain"`
// User Credential fields
// (These typically come from gcloud auth.)
@@ -131,6 +135,9 @@ type credentialsFile struct {
QuotaProjectID string `json:"quota_project_id"`
WorkforcePoolUserProject string `json:"workforce_pool_user_project"`
+ // External Account Authorized User fields
+ RevokeURL string `json:"revoke_url"`
+
// Service account impersonation
SourceCredentials *credentialsFile `json:"source_credentials"`
}
@@ -199,6 +206,19 @@ func (f *credentialsFile) tokenSource(ctx context.Context, params CredentialsPar
WorkforcePoolUserProject: f.WorkforcePoolUserProject,
}
return cfg.TokenSource(ctx)
+ case externalAccountAuthorizedUserKey:
+ cfg := &externalaccountauthorizeduser.Config{
+ Audience: f.Audience,
+ RefreshToken: f.RefreshToken,
+ TokenURL: f.TokenURLExternal,
+ TokenInfoURL: f.TokenInfoURL,
+ ClientID: f.ClientID,
+ ClientSecret: f.ClientSecret,
+ RevokeURL: f.RevokeURL,
+ QuotaProjectID: f.QuotaProjectID,
+ Scopes: params.Scopes,
+ }
+ return cfg.TokenSource(ctx)
case impersonatedServiceAccount:
if f.ServiceAccountImpersonationURL == "" || f.SourceCredentials == nil {
return nil, errors.New("missing 'source_credentials' field or 'service_account_impersonation_url' in credentials")
diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccount/aws.go b/vendor/golang.org/x/oauth2/google/internal/externalaccount/aws.go
index 2bf3202b2..bd4efd19b 100644
--- a/vendor/golang.org/x/oauth2/google/internal/externalaccount/aws.go
+++ b/vendor/golang.org/x/oauth2/google/internal/externalaccount/aws.go
@@ -274,49 +274,6 @@ type awsRequest struct {
Headers []awsRequestHeader `json:"headers"`
}
-func (cs awsCredentialSource) validateMetadataServers() error {
- if err := cs.validateMetadataServer(cs.RegionURL, "region_url"); err != nil {
- return err
- }
- if err := cs.validateMetadataServer(cs.CredVerificationURL, "url"); err != nil {
- return err
- }
- return cs.validateMetadataServer(cs.IMDSv2SessionTokenURL, "imdsv2_session_token_url")
-}
-
-var validHostnames []string = []string{"169.254.169.254", "fd00:ec2::254"}
-
-func (cs awsCredentialSource) isValidMetadataServer(metadataUrl string) bool {
- if metadataUrl == "" {
- // Zero value means use default, which is valid.
- return true
- }
-
- u, err := url.Parse(metadataUrl)
- if err != nil {
- // Unparseable URL means invalid
- return false
- }
-
- for _, validHostname := range validHostnames {
- if u.Hostname() == validHostname {
- // If it's one of the valid hostnames, everything is good
- return true
- }
- }
-
- // hostname not found in our allowlist, so not valid
- return false
-}
-
-func (cs awsCredentialSource) validateMetadataServer(metadataUrl, urlName string) error {
- if !cs.isValidMetadataServer(metadataUrl) {
- return fmt.Errorf("oauth2/google: invalid hostname %s for %s", metadataUrl, urlName)
- }
-
- return nil
-}
-
func (cs awsCredentialSource) doRequest(req *http.Request) (*http.Response, error) {
if cs.client == nil {
cs.client = oauth2.NewClient(cs.ctx, nil)
@@ -339,6 +296,10 @@ func shouldUseMetadataServer() bool {
return !canRetrieveRegionFromEnvironment() || !canRetrieveSecurityCredentialFromEnvironment()
}
+func (cs awsCredentialSource) credentialSourceType() string {
+ return "aws"
+}
+
func (cs awsCredentialSource) subjectToken() (string, error) {
if cs.requestSigner == nil {
headers := make(map[string]string)
diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccount/basecredentials.go b/vendor/golang.org/x/oauth2/google/internal/externalaccount/basecredentials.go
index dcd252a61..33288d367 100644
--- a/vendor/golang.org/x/oauth2/google/internal/externalaccount/basecredentials.go
+++ b/vendor/golang.org/x/oauth2/google/internal/externalaccount/basecredentials.go
@@ -8,13 +8,12 @@ import (
"context"
"fmt"
"net/http"
- "net/url"
"regexp"
"strconv"
- "strings"
"time"
"golang.org/x/oauth2"
+ "golang.org/x/oauth2/google/internal/stsexchange"
)
// now aliases time.Now for testing
@@ -63,31 +62,10 @@ type Config struct {
WorkforcePoolUserProject string
}
-// Each element consists of a list of patterns. validateURLs checks for matches
-// that include all elements in a given list, in that order.
-
var (
validWorkforceAudiencePattern *regexp.Regexp = regexp.MustCompile(`//iam\.googleapis\.com/locations/[^/]+/workforcePools/`)
)
-func validateURL(input string, patterns []*regexp.Regexp, scheme string) bool {
- parsed, err := url.Parse(input)
- if err != nil {
- return false
- }
- if !strings.EqualFold(parsed.Scheme, scheme) {
- return false
- }
- toTest := parsed.Host
-
- for _, pattern := range patterns {
- if pattern.MatchString(toTest) {
- return true
- }
- }
- return false
-}
-
func validateWorkforceAudience(input string) bool {
return validWorkforceAudiencePattern.MatchString(input)
}
@@ -185,10 +163,6 @@ func (c *Config) parse(ctx context.Context) (baseCredentialSource, error) {
awsCredSource.IMDSv2SessionTokenURL = c.CredentialSource.IMDSv2SessionTokenURL
}
- if err := awsCredSource.validateMetadataServers(); err != nil {
- return nil, err
- }
-
return awsCredSource, nil
}
} else if c.CredentialSource.File != "" {
@@ -202,6 +176,7 @@ func (c *Config) parse(ctx context.Context) (baseCredentialSource, error) {
}
type baseCredentialSource interface {
+ credentialSourceType() string
subjectToken() (string, error)
}
@@ -211,6 +186,15 @@ type tokenSource struct {
conf *Config
}
+func getMetricsHeaderValue(conf *Config, credSource baseCredentialSource) string {
+ return fmt.Sprintf("gl-go/%s auth/%s google-byoid-sdk source/%s sa-impersonation/%t config-lifetime/%t",
+ goVersion(),
+ "unknown",
+ credSource.credentialSourceType(),
+ conf.ServiceAccountImpersonationURL != "",
+ conf.ServiceAccountImpersonationLifetimeSeconds != 0)
+}
+
// Token allows tokenSource to conform to the oauth2.TokenSource interface.
func (ts tokenSource) Token() (*oauth2.Token, error) {
conf := ts.conf
@@ -224,7 +208,7 @@ func (ts tokenSource) Token() (*oauth2.Token, error) {
if err != nil {
return nil, err
}
- stsRequest := stsTokenExchangeRequest{
+ stsRequest := stsexchange.TokenExchangeRequest{
GrantType: "urn:ietf:params:oauth:grant-type:token-exchange",
Audience: conf.Audience,
Scope: conf.Scopes,
@@ -234,7 +218,8 @@ func (ts tokenSource) Token() (*oauth2.Token, error) {
}
header := make(http.Header)
header.Add("Content-Type", "application/x-www-form-urlencoded")
- clientAuth := clientAuthentication{
+ header.Add("x-goog-api-client", getMetricsHeaderValue(conf, credSource))
+ clientAuth := stsexchange.ClientAuthentication{
AuthStyle: oauth2.AuthStyleInHeader,
ClientID: conf.ClientID,
ClientSecret: conf.ClientSecret,
@@ -247,7 +232,7 @@ func (ts tokenSource) Token() (*oauth2.Token, error) {
"userProject": conf.WorkforcePoolUserProject,
}
}
- stsResp, err := exchangeToken(ts.ctx, conf.TokenURL, &stsRequest, clientAuth, header, options)
+ stsResp, err := stsexchange.ExchangeToken(ts.ctx, conf.TokenURL, &stsRequest, clientAuth, header, options)
if err != nil {
return nil, err
}
diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccount/executablecredsource.go b/vendor/golang.org/x/oauth2/google/internal/externalaccount/executablecredsource.go
index 579bcce5f..6497dc022 100644
--- a/vendor/golang.org/x/oauth2/google/internal/externalaccount/executablecredsource.go
+++ b/vendor/golang.org/x/oauth2/google/internal/externalaccount/executablecredsource.go
@@ -233,6 +233,10 @@ func (cs executableCredentialSource) parseSubjectTokenFromSource(response []byte
return "", tokenTypeError(source)
}
+func (cs executableCredentialSource) credentialSourceType() string {
+ return "executable"
+}
+
func (cs executableCredentialSource) subjectToken() (string, error) {
if token, err := cs.getTokenFromOutputFile(); token != "" || err != nil {
return token, err
diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccount/filecredsource.go b/vendor/golang.org/x/oauth2/google/internal/externalaccount/filecredsource.go
index e953ddb47..f35f73c5c 100644
--- a/vendor/golang.org/x/oauth2/google/internal/externalaccount/filecredsource.go
+++ b/vendor/golang.org/x/oauth2/google/internal/externalaccount/filecredsource.go
@@ -19,6 +19,10 @@ type fileCredentialSource struct {
Format format
}
+func (cs fileCredentialSource) credentialSourceType() string {
+ return "file"
+}
+
func (cs fileCredentialSource) subjectToken() (string, error) {
tokenFile, err := os.Open(cs.File)
if err != nil {
diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccount/header.go b/vendor/golang.org/x/oauth2/google/internal/externalaccount/header.go
new file mode 100644
index 000000000..1d5aad2e2
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/internal/externalaccount/header.go
@@ -0,0 +1,64 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package externalaccount
+
+import (
+ "runtime"
+ "strings"
+ "unicode"
+)
+
+var (
+ // version is a package internal global variable for testing purposes.
+ version = runtime.Version
+)
+
+// versionUnknown is only used when the runtime version cannot be determined.
+const versionUnknown = "UNKNOWN"
+
+// goVersion returns a Go runtime version derived from the runtime environment
+// that is modified to be suitable for reporting in a header, meaning it has no
+// whitespace. If it is unable to determine the Go runtime version, it returns
+// versionUnknown.
+func goVersion() string {
+ const develPrefix = "devel +"
+
+ s := version()
+ if strings.HasPrefix(s, develPrefix) {
+ s = s[len(develPrefix):]
+ if p := strings.IndexFunc(s, unicode.IsSpace); p >= 0 {
+ s = s[:p]
+ }
+ return s
+ } else if p := strings.IndexFunc(s, unicode.IsSpace); p >= 0 {
+ s = s[:p]
+ }
+
+ notSemverRune := func(r rune) bool {
+ return !strings.ContainsRune("0123456789.", r)
+ }
+
+ if strings.HasPrefix(s, "go1") {
+ s = s[2:]
+ var prerelease string
+ if p := strings.IndexFunc(s, notSemverRune); p >= 0 {
+ s, prerelease = s[:p], s[p:]
+ }
+ if strings.HasSuffix(s, ".") {
+ s += "0"
+ } else if strings.Count(s, ".") < 2 {
+ s += ".0"
+ }
+ if prerelease != "" {
+ // Some release candidates already have a dash in them.
+ if !strings.HasPrefix(prerelease, "-") {
+ prerelease = "-" + prerelease
+ }
+ s += prerelease
+ }
+ return s
+ }
+ return "UNKNOWN"
+}
diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccount/urlcredsource.go b/vendor/golang.org/x/oauth2/google/internal/externalaccount/urlcredsource.go
index 16dca6541..606bb4e80 100644
--- a/vendor/golang.org/x/oauth2/google/internal/externalaccount/urlcredsource.go
+++ b/vendor/golang.org/x/oauth2/google/internal/externalaccount/urlcredsource.go
@@ -23,6 +23,10 @@ type urlCredentialSource struct {
ctx context.Context
}
+func (cs urlCredentialSource) credentialSourceType() string {
+ return "url"
+}
+
func (cs urlCredentialSource) subjectToken() (string, error) {
client := oauth2.NewClient(cs.ctx, nil)
req, err := http.NewRequest("GET", cs.URL, nil)
diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccountauthorizeduser/externalaccountauthorizeduser.go b/vendor/golang.org/x/oauth2/google/internal/externalaccountauthorizeduser/externalaccountauthorizeduser.go
new file mode 100644
index 000000000..cb5820707
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/internal/externalaccountauthorizeduser/externalaccountauthorizeduser.go
@@ -0,0 +1,114 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package externalaccountauthorizeduser
+
+import (
+ "context"
+ "errors"
+ "time"
+
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/google/internal/stsexchange"
+)
+
+// now aliases time.Now for testing.
+var now = func() time.Time {
+ return time.Now().UTC()
+}
+
+var tokenValid = func(token oauth2.Token) bool {
+ return token.Valid()
+}
+
+type Config struct {
+ // Audience is the Secure Token Service (STS) audience which contains the resource name for the workforce pool and
+ // the provider identifier in that pool.
+ Audience string
+ // RefreshToken is the optional OAuth 2.0 refresh token. If specified, credentials can be refreshed.
+ RefreshToken string
+ // TokenURL is the optional STS token exchange endpoint for refresh. Must be specified for refresh, can be left as
+ // None if the token can not be refreshed.
+ TokenURL string
+ // TokenInfoURL is the optional STS endpoint URL for token introspection.
+ TokenInfoURL string
+ // ClientID is only required in conjunction with ClientSecret, as described above.
+ ClientID string
+ // ClientSecret is currently only required if token_info endpoint also needs to be called with the generated GCP
+ // access token. When provided, STS will be called with additional basic authentication using client_id as username
+ // and client_secret as password.
+ ClientSecret string
+ // Token is the OAuth2.0 access token. Can be nil if refresh information is provided.
+ Token string
+ // Expiry is the optional expiration datetime of the OAuth 2.0 access token.
+ Expiry time.Time
+ // RevokeURL is the optional STS endpoint URL for revoking tokens.
+ RevokeURL string
+ // QuotaProjectID is the optional project ID used for quota and billing. This project may be different from the
+ // project used to create the credentials.
+ QuotaProjectID string
+ Scopes []string
+}
+
+func (c *Config) canRefresh() bool {
+ return c.ClientID != "" && c.ClientSecret != "" && c.RefreshToken != "" && c.TokenURL != ""
+}
+
+func (c *Config) TokenSource(ctx context.Context) (oauth2.TokenSource, error) {
+ var token oauth2.Token
+ if c.Token != "" && !c.Expiry.IsZero() {
+ token = oauth2.Token{
+ AccessToken: c.Token,
+ Expiry: c.Expiry,
+ TokenType: "Bearer",
+ }
+ }
+ if !tokenValid(token) && !c.canRefresh() {
+ return nil, errors.New("oauth2/google: Token should be created with fields to make it valid (`token` and `expiry`), or fields to allow it to refresh (`refresh_token`, `token_url`, `client_id`, `client_secret`).")
+ }
+
+ ts := tokenSource{
+ ctx: ctx,
+ conf: c,
+ }
+
+ return oauth2.ReuseTokenSource(&token, ts), nil
+}
+
+type tokenSource struct {
+ ctx context.Context
+ conf *Config
+}
+
+func (ts tokenSource) Token() (*oauth2.Token, error) {
+ conf := ts.conf
+ if !conf.canRefresh() {
+ return nil, errors.New("oauth2/google: The credentials do not contain the necessary fields need to refresh the access token. You must specify refresh_token, token_url, client_id, and client_secret.")
+ }
+
+ clientAuth := stsexchange.ClientAuthentication{
+ AuthStyle: oauth2.AuthStyleInHeader,
+ ClientID: conf.ClientID,
+ ClientSecret: conf.ClientSecret,
+ }
+
+ stsResponse, err := stsexchange.RefreshAccessToken(ts.ctx, conf.TokenURL, conf.RefreshToken, clientAuth, nil)
+ if err != nil {
+ return nil, err
+ }
+ if stsResponse.ExpiresIn < 0 {
+ return nil, errors.New("oauth2/google: got invalid expiry from security token service")
+ }
+
+ if stsResponse.RefreshToken != "" {
+ conf.RefreshToken = stsResponse.RefreshToken
+ }
+
+ token := &oauth2.Token{
+ AccessToken: stsResponse.AccessToken,
+ Expiry: now().Add(time.Duration(stsResponse.ExpiresIn) * time.Second),
+ TokenType: "Bearer",
+ }
+ return token, nil
+}
diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccount/clientauth.go b/vendor/golang.org/x/oauth2/google/internal/stsexchange/clientauth.go
index 99987ce29..ebd520eac 100644
--- a/vendor/golang.org/x/oauth2/google/internal/externalaccount/clientauth.go
+++ b/vendor/golang.org/x/oauth2/google/internal/stsexchange/clientauth.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package externalaccount
+package stsexchange
import (
"encoding/base64"
@@ -12,8 +12,8 @@ import (
"golang.org/x/oauth2"
)
-// clientAuthentication represents an OAuth client ID and secret and the mechanism for passing these credentials as stated in rfc6749#2.3.1.
-type clientAuthentication struct {
+// ClientAuthentication represents an OAuth client ID and secret and the mechanism for passing these credentials as stated in rfc6749#2.3.1.
+type ClientAuthentication struct {
// AuthStyle can be either basic or request-body
AuthStyle oauth2.AuthStyle
ClientID string
@@ -23,7 +23,7 @@ type clientAuthentication struct {
// InjectAuthentication is used to add authentication to a Secure Token Service exchange
// request. It modifies either the passed url.Values or http.Header depending on the desired
// authentication format.
-func (c *clientAuthentication) InjectAuthentication(values url.Values, headers http.Header) {
+func (c *ClientAuthentication) InjectAuthentication(values url.Values, headers http.Header) {
if c.ClientID == "" || c.ClientSecret == "" || values == nil || headers == nil {
return
}
diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccount/sts_exchange.go b/vendor/golang.org/x/oauth2/google/internal/stsexchange/sts_exchange.go
index e6fcae5fc..1a0bebd15 100644
--- a/vendor/golang.org/x/oauth2/google/internal/externalaccount/sts_exchange.go
+++ b/vendor/golang.org/x/oauth2/google/internal/stsexchange/sts_exchange.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package externalaccount
+package stsexchange
import (
"context"
@@ -18,14 +18,17 @@ import (
"golang.org/x/oauth2"
)
-// exchangeToken performs an oauth2 token exchange with the provided endpoint.
+func defaultHeader() http.Header {
+ header := make(http.Header)
+ header.Add("Content-Type", "application/x-www-form-urlencoded")
+ return header
+}
+
+// ExchangeToken performs an oauth2 token exchange with the provided endpoint.
// The first 4 fields are all mandatory. headers can be used to pass additional
// headers beyond the bare minimum required by the token exchange. options can
// be used to pass additional JSON-structured options to the remote server.
-func exchangeToken(ctx context.Context, endpoint string, request *stsTokenExchangeRequest, authentication clientAuthentication, headers http.Header, options map[string]interface{}) (*stsTokenExchangeResponse, error) {
-
- client := oauth2.NewClient(ctx, nil)
-
+func ExchangeToken(ctx context.Context, endpoint string, request *TokenExchangeRequest, authentication ClientAuthentication, headers http.Header, options map[string]interface{}) (*Response, error) {
data := url.Values{}
data.Set("audience", request.Audience)
data.Set("grant_type", "urn:ietf:params:oauth:grant-type:token-exchange")
@@ -41,13 +44,28 @@ func exchangeToken(ctx context.Context, endpoint string, request *stsTokenExchan
data.Set("options", string(opts))
}
+ return makeRequest(ctx, endpoint, data, authentication, headers)
+}
+
+func RefreshAccessToken(ctx context.Context, endpoint string, refreshToken string, authentication ClientAuthentication, headers http.Header) (*Response, error) {
+ data := url.Values{}
+ data.Set("grant_type", "refresh_token")
+ data.Set("refresh_token", refreshToken)
+
+ return makeRequest(ctx, endpoint, data, authentication, headers)
+}
+
+func makeRequest(ctx context.Context, endpoint string, data url.Values, authentication ClientAuthentication, headers http.Header) (*Response, error) {
+ if headers == nil {
+ headers = defaultHeader()
+ }
+ client := oauth2.NewClient(ctx, nil)
authentication.InjectAuthentication(data, headers)
encodedData := data.Encode()
req, err := http.NewRequest("POST", endpoint, strings.NewReader(encodedData))
if err != nil {
return nil, fmt.Errorf("oauth2/google: failed to properly build http request: %v", err)
-
}
req = req.WithContext(ctx)
for key, list := range headers {
@@ -71,7 +89,7 @@ func exchangeToken(ctx context.Context, endpoint string, request *stsTokenExchan
if c := resp.StatusCode; c < 200 || c > 299 {
return nil, fmt.Errorf("oauth2/google: status code %d: %s", c, body)
}
- var stsResp stsTokenExchangeResponse
+ var stsResp Response
err = json.Unmarshal(body, &stsResp)
if err != nil {
return nil, fmt.Errorf("oauth2/google: failed to unmarshal response body from Secure Token Server: %v", err)
@@ -81,8 +99,8 @@ func exchangeToken(ctx context.Context, endpoint string, request *stsTokenExchan
return &stsResp, nil
}
-// stsTokenExchangeRequest contains fields necessary to make an oauth2 token exchange.
-type stsTokenExchangeRequest struct {
+// TokenExchangeRequest contains fields necessary to make an oauth2 token exchange.
+type TokenExchangeRequest struct {
ActingParty struct {
ActorToken string
ActorTokenType string
@@ -96,8 +114,8 @@ type stsTokenExchangeRequest struct {
SubjectTokenType string
}
-// stsTokenExchangeResponse is used to decode the remote server response during an oauth2 token exchange.
-type stsTokenExchangeResponse struct {
+// Response is used to decode the remote server response during an oauth2 token exchange.
+type Response struct {
AccessToken string `json:"access_token"`
IssuedTokenType string `json:"issued_token_type"`
TokenType string `json:"token_type"`
diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go
index cc7c98c25..90a2c3d6d 100644
--- a/vendor/golang.org/x/oauth2/oauth2.go
+++ b/vendor/golang.org/x/oauth2/oauth2.go
@@ -75,8 +75,9 @@ type TokenSource interface {
// Endpoint represents an OAuth 2.0 provider's authorization and token
// endpoint URLs.
type Endpoint struct {
- AuthURL string
- TokenURL string
+ AuthURL string
+ DeviceAuthURL string
+ TokenURL string
// AuthStyle optionally specifies how the endpoint wants the
// client ID & client secret sent. The zero value means to
@@ -143,15 +144,19 @@ func SetAuthURLParam(key, value string) AuthCodeOption {
// AuthCodeURL returns a URL to OAuth 2.0 provider's consent page
// that asks for permissions for the required scopes explicitly.
//
-// State is a token to protect the user from CSRF attacks. You must
-// always provide a non-empty string and validate that it matches the
-// state query parameter on your redirect callback.
-// See http://tools.ietf.org/html/rfc6749#section-10.12 for more info.
+// State is an opaque value used by the client to maintain state between the
+// request and callback. The authorization server includes this value when
+// redirecting the user agent back to the client.
//
// Opts may include AccessTypeOnline or AccessTypeOffline, as well
// as ApprovalForce.
-// It can also be used to pass the PKCE challenge.
-// See https://www.oauth.com/oauth2-servers/pkce/ for more info.
+//
+// To protect against CSRF attacks, opts should include a PKCE challenge
+// (S256ChallengeOption). Not all servers support PKCE. An alternative is to
+// generate a random state parameter and verify it after exchange.
+// See https://datatracker.ietf.org/doc/html/rfc6749#section-10.12 (predating
+// PKCE), https://www.oauth.com/oauth2-servers/pkce/ and
+// https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-09.html#name-cross-site-request-forgery (describing both approaches)
func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string {
var buf bytes.Buffer
buf.WriteString(c.Endpoint.AuthURL)
@@ -166,7 +171,6 @@ func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string {
v.Set("scope", strings.Join(c.Scopes, " "))
}
if state != "" {
- // TODO(light): Docs say never to omit state; don't allow empty.
v.Set("state", state)
}
for _, opt := range opts {
@@ -211,10 +215,11 @@ func (c *Config) PasswordCredentialsToken(ctx context.Context, username, passwor
// The provided context optionally controls which HTTP client is used. See the HTTPClient variable.
//
// The code will be in the *http.Request.FormValue("code"). Before
-// calling Exchange, be sure to validate FormValue("state").
+// calling Exchange, be sure to validate FormValue("state") if you are
+// using it to protect against CSRF attacks.
//
-// Opts may include the PKCE verifier code if previously used in AuthCodeURL.
-// See https://www.oauth.com/oauth2-servers/pkce/ for more info.
+// If using PKCE to protect against CSRF attacks, opts should include a
+// VerifierOption.
func (c *Config) Exchange(ctx context.Context, code string, opts ...AuthCodeOption) (*Token, error) {
v := url.Values{
"grant_type": {"authorization_code"},
diff --git a/vendor/golang.org/x/oauth2/pkce.go b/vendor/golang.org/x/oauth2/pkce.go
new file mode 100644
index 000000000..50593b6df
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/pkce.go
@@ -0,0 +1,68 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+package oauth2
+
+import (
+ "crypto/rand"
+ "crypto/sha256"
+ "encoding/base64"
+ "net/url"
+)
+
+const (
+ codeChallengeKey = "code_challenge"
+ codeChallengeMethodKey = "code_challenge_method"
+ codeVerifierKey = "code_verifier"
+)
+
+// GenerateVerifier generates a PKCE code verifier with 32 octets of randomness.
+// This follows recommendations in RFC 7636.
+//
+// A fresh verifier should be generated for each authorization.
+// S256ChallengeOption(verifier) should then be passed to Config.AuthCodeURL
+// (or Config.DeviceAccess) and VerifierOption(verifier) to Config.Exchange
+// (or Config.DeviceAccessToken).
+func GenerateVerifier() string {
+ // "RECOMMENDED that the output of a suitable random number generator be
+ // used to create a 32-octet sequence. The octet sequence is then
+ // base64url-encoded to produce a 43-octet URL-safe string to use as the
+ // code verifier."
+ // https://datatracker.ietf.org/doc/html/rfc7636#section-4.1
+ data := make([]byte, 32)
+ if _, err := rand.Read(data); err != nil {
+ panic(err)
+ }
+ return base64.RawURLEncoding.EncodeToString(data)
+}
+
+// VerifierOption returns a PKCE code verifier AuthCodeOption. It should be
+// passed to Config.Exchange or Config.DeviceAccessToken only.
+func VerifierOption(verifier string) AuthCodeOption {
+ return setParam{k: codeVerifierKey, v: verifier}
+}
+
+// S256ChallengeFromVerifier returns a PKCE code challenge derived from verifier with method S256.
+//
+// Prefer to use S256ChallengeOption where possible.
+func S256ChallengeFromVerifier(verifier string) string {
+ sha := sha256.Sum256([]byte(verifier))
+ return base64.RawURLEncoding.EncodeToString(sha[:])
+}
+
+// S256ChallengeOption derives a PKCE code challenge derived from verifier with
+// method S256. It should be passed to Config.AuthCodeURL or Config.DeviceAccess
+// only.
+func S256ChallengeOption(verifier string) AuthCodeOption {
+ return challengeOption{
+ challenge_method: "S256",
+ challenge: S256ChallengeFromVerifier(verifier),
+ }
+}
+
+type challengeOption struct{ challenge_method, challenge string }
+
+func (p challengeOption) setValue(m url.Values) {
+ m.Set(codeChallengeMethodKey, p.challenge_method)
+ m.Set(codeChallengeKey, p.challenge)
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index f177d9613..e66ac47a8 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -823,12 +823,14 @@ golang.org/x/net/http2/hpack
golang.org/x/net/idna
golang.org/x/net/internal/timeseries
golang.org/x/net/trace
-# golang.org/x/oauth2 v0.12.0
+# golang.org/x/oauth2 v0.13.0
## explicit; go 1.18
golang.org/x/oauth2
golang.org/x/oauth2/authhandler
golang.org/x/oauth2/google
golang.org/x/oauth2/google/internal/externalaccount
+golang.org/x/oauth2/google/internal/externalaccountauthorizeduser
+golang.org/x/oauth2/google/internal/stsexchange
golang.org/x/oauth2/internal
golang.org/x/oauth2/jws
golang.org/x/oauth2/jwt