diff options
author | 2025-03-09 17:47:56 +0100 | |
---|---|---|
committer | 2025-03-10 01:59:49 +0100 | |
commit | 3ac1ee16f377d31a0fb80c8dae28b6239ac4229e (patch) | |
tree | f61faa581feaaeaba2542b9f2b8234a590684413 /vendor/golang.org/x/oauth2/internal/token.go | |
parent | [chore] update URLs to forked source (diff) | |
download | gotosocial-3ac1ee16f377d31a0fb80c8dae28b6239ac4229e.tar.xz |
[chore] remove vendor
Diffstat (limited to 'vendor/golang.org/x/oauth2/internal/token.go')
-rw-r--r-- | vendor/golang.org/x/oauth2/internal/token.go | 352 |
1 files changed, 0 insertions, 352 deletions
diff --git a/vendor/golang.org/x/oauth2/internal/token.go b/vendor/golang.org/x/oauth2/internal/token.go deleted file mode 100644 index e83ddeef0..000000000 --- a/vendor/golang.org/x/oauth2/internal/token.go +++ /dev/null @@ -1,352 +0,0 @@ -// Copyright 2014 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 internal - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "math" - "mime" - "net/http" - "net/url" - "strconv" - "strings" - "sync" - "sync/atomic" - "time" -) - -// Token represents the credentials used to authorize -// the requests to access protected resources on the OAuth 2.0 -// provider's backend. -// -// This type is a mirror of oauth2.Token and exists to break -// an otherwise-circular dependency. Other internal packages -// should convert this Token into an oauth2.Token before use. -type Token struct { - // AccessToken is the token that authorizes and authenticates - // the requests. - AccessToken string - - // TokenType is the type of token. - // The Type method returns either this or "Bearer", the default. - TokenType string - - // RefreshToken is a token that's used by the application - // (as opposed to the user) to refresh the access token - // if it expires. - RefreshToken string - - // Expiry is the optional expiration time of the access token. - // - // If zero, TokenSource implementations will reuse the same - // token forever and RefreshToken or equivalent - // mechanisms for that TokenSource will not be used. - Expiry time.Time - - // Raw optionally contains extra metadata from the server - // when updating a token. - Raw interface{} -} - -// tokenJSON is the struct representing the HTTP response from OAuth2 -// providers returning a token or error in JSON form. -// https://datatracker.ietf.org/doc/html/rfc6749#section-5.1 -type tokenJSON struct { - AccessToken string `json:"access_token"` - TokenType string `json:"token_type"` - RefreshToken string `json:"refresh_token"` - ExpiresIn expirationTime `json:"expires_in"` // at least PayPal returns string, while most return number - // error fields - // https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 - ErrorCode string `json:"error"` - ErrorDescription string `json:"error_description"` - ErrorURI string `json:"error_uri"` -} - -func (e *tokenJSON) expiry() (t time.Time) { - if v := e.ExpiresIn; v != 0 { - return time.Now().Add(time.Duration(v) * time.Second) - } - return -} - -type expirationTime int32 - -func (e *expirationTime) UnmarshalJSON(b []byte) error { - if len(b) == 0 || string(b) == "null" { - return nil - } - var n json.Number - err := json.Unmarshal(b, &n) - if err != nil { - return err - } - i, err := n.Int64() - if err != nil { - return err - } - if i > math.MaxInt32 { - i = math.MaxInt32 - } - *e = expirationTime(i) - return nil -} - -// RegisterBrokenAuthHeaderProvider previously did something. It is now a no-op. -// -// Deprecated: this function no longer does anything. Caller code that -// wants to avoid potential extra HTTP requests made during -// auto-probing of the provider's auth style should set -// Endpoint.AuthStyle. -func RegisterBrokenAuthHeaderProvider(tokenURL string) {} - -// AuthStyle is a copy of the golang.org/x/oauth2 package's AuthStyle type. -type AuthStyle int - -const ( - AuthStyleUnknown AuthStyle = 0 - AuthStyleInParams AuthStyle = 1 - AuthStyleInHeader AuthStyle = 2 -) - -// LazyAuthStyleCache is a backwards compatibility compromise to let Configs -// have a lazily-initialized AuthStyleCache. -// -// The two users of this, oauth2.Config and oauth2/clientcredentials.Config, -// both would ideally just embed an unexported AuthStyleCache but because both -// were historically allowed to be copied by value we can't retroactively add an -// uncopyable Mutex to them. -// -// We could use an atomic.Pointer, but that was added recently enough (in Go -// 1.18) that we'd break Go 1.17 users where the tests as of 2023-08-03 -// still pass. By using an atomic.Value, it supports both Go 1.17 and -// copying by value, even if that's not ideal. -type LazyAuthStyleCache struct { - v atomic.Value // of *AuthStyleCache -} - -func (lc *LazyAuthStyleCache) Get() *AuthStyleCache { - if c, ok := lc.v.Load().(*AuthStyleCache); ok { - return c - } - c := new(AuthStyleCache) - if !lc.v.CompareAndSwap(nil, c) { - c = lc.v.Load().(*AuthStyleCache) - } - return c -} - -// AuthStyleCache is the set of tokenURLs we've successfully used via -// RetrieveToken and which style auth we ended up using. -// It's called a cache, but it doesn't (yet?) shrink. It's expected that -// the set of OAuth2 servers a program contacts over time is fixed and -// small. -type AuthStyleCache struct { - mu sync.Mutex - m map[string]AuthStyle // keyed by tokenURL -} - -// lookupAuthStyle reports which auth style we last used with tokenURL -// when calling RetrieveToken and whether we have ever done so. -func (c *AuthStyleCache) lookupAuthStyle(tokenURL string) (style AuthStyle, ok bool) { - c.mu.Lock() - defer c.mu.Unlock() - style, ok = c.m[tokenURL] - return -} - -// setAuthStyle adds an entry to authStyleCache, documented above. -func (c *AuthStyleCache) setAuthStyle(tokenURL string, v AuthStyle) { - c.mu.Lock() - defer c.mu.Unlock() - if c.m == nil { - c.m = make(map[string]AuthStyle) - } - c.m[tokenURL] = v -} - -// newTokenRequest returns a new *http.Request to retrieve a new token -// from tokenURL using the provided clientID, clientSecret, and POST -// body parameters. -// -// inParams is whether the clientID & clientSecret should be encoded -// as the POST body. An 'inParams' value of true means to send it in -// the POST body (along with any values in v); false means to send it -// in the Authorization header. -func newTokenRequest(tokenURL, clientID, clientSecret string, v url.Values, authStyle AuthStyle) (*http.Request, error) { - if authStyle == AuthStyleInParams { - v = cloneURLValues(v) - if clientID != "" { - v.Set("client_id", clientID) - } - if clientSecret != "" { - v.Set("client_secret", clientSecret) - } - } - req, err := http.NewRequest("POST", tokenURL, strings.NewReader(v.Encode())) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - if authStyle == AuthStyleInHeader { - req.SetBasicAuth(url.QueryEscape(clientID), url.QueryEscape(clientSecret)) - } - return req, nil -} - -func cloneURLValues(v url.Values) url.Values { - v2 := make(url.Values, len(v)) - for k, vv := range v { - v2[k] = append([]string(nil), vv...) - } - return v2 -} - -func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values, authStyle AuthStyle, styleCache *AuthStyleCache) (*Token, error) { - needsAuthStyleProbe := authStyle == 0 - if needsAuthStyleProbe { - if style, ok := styleCache.lookupAuthStyle(tokenURL); ok { - authStyle = style - needsAuthStyleProbe = false - } else { - authStyle = AuthStyleInHeader // the first way we'll try - } - } - req, err := newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle) - if err != nil { - return nil, err - } - token, err := doTokenRoundTrip(ctx, req) - if err != nil && needsAuthStyleProbe { - // If we get an error, assume the server wants the - // clientID & clientSecret in a different form. - // See https://code.google.com/p/goauth2/issues/detail?id=31 for background. - // In summary: - // - Reddit only accepts client secret in the Authorization header - // - Dropbox accepts either it in URL param or Auth header, but not both. - // - Google only accepts URL param (not spec compliant?), not Auth header - // - Stripe only accepts client secret in Auth header with Bearer method, not Basic - // - // We used to maintain a big table in this code of all the sites and which way - // they went, but maintaining it didn't scale & got annoying. - // So just try both ways. - authStyle = AuthStyleInParams // the second way we'll try - req, _ = newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle) - token, err = doTokenRoundTrip(ctx, req) - } - if needsAuthStyleProbe && err == nil { - styleCache.setAuthStyle(tokenURL, authStyle) - } - // Don't overwrite `RefreshToken` with an empty value - // if this was a token refreshing request. - if token != nil && token.RefreshToken == "" { - token.RefreshToken = v.Get("refresh_token") - } - return token, err -} - -func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) { - r, err := ContextClient(ctx).Do(req.WithContext(ctx)) - if err != nil { - return nil, err - } - body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1<<20)) - r.Body.Close() - if err != nil { - return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err) - } - - failureStatus := r.StatusCode < 200 || r.StatusCode > 299 - retrieveError := &RetrieveError{ - Response: r, - Body: body, - // attempt to populate error detail below - } - - var token *Token - content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type")) - switch content { - case "application/x-www-form-urlencoded", "text/plain": - // some endpoints return a query string - vals, err := url.ParseQuery(string(body)) - if err != nil { - if failureStatus { - return nil, retrieveError - } - return nil, fmt.Errorf("oauth2: cannot parse response: %v", err) - } - retrieveError.ErrorCode = vals.Get("error") - retrieveError.ErrorDescription = vals.Get("error_description") - retrieveError.ErrorURI = vals.Get("error_uri") - token = &Token{ - AccessToken: vals.Get("access_token"), - TokenType: vals.Get("token_type"), - RefreshToken: vals.Get("refresh_token"), - Raw: vals, - } - e := vals.Get("expires_in") - expires, _ := strconv.Atoi(e) - if expires != 0 { - token.Expiry = time.Now().Add(time.Duration(expires) * time.Second) - } - default: - var tj tokenJSON - if err = json.Unmarshal(body, &tj); err != nil { - if failureStatus { - return nil, retrieveError - } - return nil, fmt.Errorf("oauth2: cannot parse json: %v", err) - } - retrieveError.ErrorCode = tj.ErrorCode - retrieveError.ErrorDescription = tj.ErrorDescription - retrieveError.ErrorURI = tj.ErrorURI - token = &Token{ - AccessToken: tj.AccessToken, - TokenType: tj.TokenType, - RefreshToken: tj.RefreshToken, - Expiry: tj.expiry(), - Raw: make(map[string]interface{}), - } - json.Unmarshal(body, &token.Raw) // no error checks for optional fields - } - // according to spec, servers should respond status 400 in error case - // https://www.rfc-editor.org/rfc/rfc6749#section-5.2 - // but some unorthodox servers respond 200 in error case - if failureStatus || retrieveError.ErrorCode != "" { - return nil, retrieveError - } - if token.AccessToken == "" { - return nil, errors.New("oauth2: server response missing access_token") - } - return token, nil -} - -// mirrors oauth2.RetrieveError -type RetrieveError struct { - Response *http.Response - Body []byte - ErrorCode string - ErrorDescription string - ErrorURI string -} - -func (r *RetrieveError) Error() string { - if r.ErrorCode != "" { - s := fmt.Sprintf("oauth2: %q", r.ErrorCode) - if r.ErrorDescription != "" { - s += fmt.Sprintf(" %q", r.ErrorDescription) - } - if r.ErrorURI != "" { - s += fmt.Sprintf(" %q", r.ErrorURI) - } - return s - } - return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body) -} |