"Fossies" - the Fresh Open Source Software Archive

Member "gdrive-2.1.1/vendor/golang.org/x/oauth2/oauth2.go" (28 May 2021, 11198 Bytes) of package /linux/misc/gdrive-2.1.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Go source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // Copyright 2014 The Go Authors. All rights reserved.
    2 // Use of this source code is governed by a BSD-style
    3 // license that can be found in the LICENSE file.
    4 
    5 // Package oauth2 provides support for making
    6 // OAuth2 authorized and authenticated HTTP requests.
    7 // It can additionally grant authorization with Bearer JWT.
    8 package oauth2
    9 
   10 import (
   11     "bytes"
   12     "errors"
   13     "net/http"
   14     "net/url"
   15     "strings"
   16     "sync"
   17 
   18     "golang.org/x/net/context"
   19     "golang.org/x/oauth2/internal"
   20 )
   21 
   22 // NoContext is the default context you should supply if not using
   23 // your own context.Context (see https://golang.org/x/net/context).
   24 var NoContext = context.TODO()
   25 
   26 // RegisterBrokenAuthHeaderProvider registers an OAuth2 server
   27 // identified by the tokenURL prefix as an OAuth2 implementation
   28 // which doesn't support the HTTP Basic authentication
   29 // scheme to authenticate with the authorization server.
   30 // Once a server is registered, credentials (client_id and client_secret)
   31 // will be passed as query parameters rather than being present
   32 // in the Authorization header.
   33 // See https://code.google.com/p/goauth2/issues/detail?id=31 for background.
   34 func RegisterBrokenAuthHeaderProvider(tokenURL string) {
   35     internal.RegisterBrokenAuthHeaderProvider(tokenURL)
   36 }
   37 
   38 // Config describes a typical 3-legged OAuth2 flow, with both the
   39 // client application information and the server's endpoint URLs.
   40 type Config struct {
   41     // ClientID is the application's ID.
   42     ClientID string
   43 
   44     // ClientSecret is the application's secret.
   45     ClientSecret string
   46 
   47     // Endpoint contains the resource server's token endpoint
   48     // URLs. These are constants specific to each server and are
   49     // often available via site-specific packages, such as
   50     // google.Endpoint or github.Endpoint.
   51     Endpoint Endpoint
   52 
   53     // RedirectURL is the URL to redirect users going through
   54     // the OAuth flow, after the resource owner's URLs.
   55     RedirectURL string
   56 
   57     // Scope specifies optional requested permissions.
   58     Scopes []string
   59 }
   60 
   61 // A TokenSource is anything that can return a token.
   62 type TokenSource interface {
   63     // Token returns a token or an error.
   64     // Token must be safe for concurrent use by multiple goroutines.
   65     // The returned Token must not be modified.
   66     Token() (*Token, error)
   67 }
   68 
   69 // Endpoint contains the OAuth 2.0 provider's authorization and token
   70 // endpoint URLs.
   71 type Endpoint struct {
   72     AuthURL  string
   73     TokenURL string
   74 }
   75 
   76 var (
   77     // AccessTypeOnline and AccessTypeOffline are options passed
   78     // to the Options.AuthCodeURL method. They modify the
   79     // "access_type" field that gets sent in the URL returned by
   80     // AuthCodeURL.
   81     //
   82     // Online is the default if neither is specified. If your
   83     // application needs to refresh access tokens when the user
   84     // is not present at the browser, then use offline. This will
   85     // result in your application obtaining a refresh token the
   86     // first time your application exchanges an authorization
   87     // code for a user.
   88     AccessTypeOnline  AuthCodeOption = SetAuthURLParam("access_type", "online")
   89     AccessTypeOffline AuthCodeOption = SetAuthURLParam("access_type", "offline")
   90 
   91     // ApprovalForce forces the users to view the consent dialog
   92     // and confirm the permissions request at the URL returned
   93     // from AuthCodeURL, even if they've already done so.
   94     ApprovalForce AuthCodeOption = SetAuthURLParam("approval_prompt", "force")
   95 )
   96 
   97 // An AuthCodeOption is passed to Config.AuthCodeURL.
   98 type AuthCodeOption interface {
   99     setValue(url.Values)
  100 }
  101 
  102 type setParam struct{ k, v string }
  103 
  104 func (p setParam) setValue(m url.Values) { m.Set(p.k, p.v) }
  105 
  106 // SetAuthURLParam builds an AuthCodeOption which passes key/value parameters
  107 // to a provider's authorization endpoint.
  108 func SetAuthURLParam(key, value string) AuthCodeOption {
  109     return setParam{key, value}
  110 }
  111 
  112 // AuthCodeURL returns a URL to OAuth 2.0 provider's consent page
  113 // that asks for permissions for the required scopes explicitly.
  114 //
  115 // State is a token to protect the user from CSRF attacks. You must
  116 // always provide a non-zero string and validate that it matches the
  117 // the state query parameter on your redirect callback.
  118 // See http://tools.ietf.org/html/rfc6749#section-10.12 for more info.
  119 //
  120 // Opts may include AccessTypeOnline or AccessTypeOffline, as well
  121 // as ApprovalForce.
  122 func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string {
  123     var buf bytes.Buffer
  124     buf.WriteString(c.Endpoint.AuthURL)
  125     v := url.Values{
  126         "response_type": {"code"},
  127         "client_id":     {c.ClientID},
  128         "redirect_uri":  internal.CondVal(c.RedirectURL),
  129         "scope":         internal.CondVal(strings.Join(c.Scopes, " ")),
  130         "state":         internal.CondVal(state),
  131     }
  132     for _, opt := range opts {
  133         opt.setValue(v)
  134     }
  135     if strings.Contains(c.Endpoint.AuthURL, "?") {
  136         buf.WriteByte('&')
  137     } else {
  138         buf.WriteByte('?')
  139     }
  140     buf.WriteString(v.Encode())
  141     return buf.String()
  142 }
  143 
  144 // PasswordCredentialsToken converts a resource owner username and password
  145 // pair into a token.
  146 //
  147 // Per the RFC, this grant type should only be used "when there is a high
  148 // degree of trust between the resource owner and the client (e.g., the client
  149 // is part of the device operating system or a highly privileged application),
  150 // and when other authorization grant types are not available."
  151 // See https://tools.ietf.org/html/rfc6749#section-4.3 for more info.
  152 //
  153 // The HTTP client to use is derived from the context.
  154 // If nil, http.DefaultClient is used.
  155 func (c *Config) PasswordCredentialsToken(ctx context.Context, username, password string) (*Token, error) {
  156     return retrieveToken(ctx, c, url.Values{
  157         "grant_type": {"password"},
  158         "username":   {username},
  159         "password":   {password},
  160         "scope":      internal.CondVal(strings.Join(c.Scopes, " ")),
  161     })
  162 }
  163 
  164 // Exchange converts an authorization code into a token.
  165 //
  166 // It is used after a resource provider redirects the user back
  167 // to the Redirect URI (the URL obtained from AuthCodeURL).
  168 //
  169 // The HTTP client to use is derived from the context.
  170 // If a client is not provided via the context, http.DefaultClient is used.
  171 //
  172 // The code will be in the *http.Request.FormValue("code"). Before
  173 // calling Exchange, be sure to validate FormValue("state").
  174 func (c *Config) Exchange(ctx context.Context, code string) (*Token, error) {
  175     return retrieveToken(ctx, c, url.Values{
  176         "grant_type":   {"authorization_code"},
  177         "code":         {code},
  178         "redirect_uri": internal.CondVal(c.RedirectURL),
  179         "scope":        internal.CondVal(strings.Join(c.Scopes, " ")),
  180     })
  181 }
  182 
  183 // Client returns an HTTP client using the provided token.
  184 // The token will auto-refresh as necessary. The underlying
  185 // HTTP transport will be obtained using the provided context.
  186 // The returned client and its Transport should not be modified.
  187 func (c *Config) Client(ctx context.Context, t *Token) *http.Client {
  188     return NewClient(ctx, c.TokenSource(ctx, t))
  189 }
  190 
  191 // TokenSource returns a TokenSource that returns t until t expires,
  192 // automatically refreshing it as necessary using the provided context.
  193 //
  194 // Most users will use Config.Client instead.
  195 func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource {
  196     tkr := &tokenRefresher{
  197         ctx:  ctx,
  198         conf: c,
  199     }
  200     if t != nil {
  201         tkr.refreshToken = t.RefreshToken
  202     }
  203     return &reuseTokenSource{
  204         t:   t,
  205         new: tkr,
  206     }
  207 }
  208 
  209 // tokenRefresher is a TokenSource that makes "grant_type"=="refresh_token"
  210 // HTTP requests to renew a token using a RefreshToken.
  211 type tokenRefresher struct {
  212     ctx          context.Context // used to get HTTP requests
  213     conf         *Config
  214     refreshToken string
  215 }
  216 
  217 // WARNING: Token is not safe for concurrent access, as it
  218 // updates the tokenRefresher's refreshToken field.
  219 // Within this package, it is used by reuseTokenSource which
  220 // synchronizes calls to this method with its own mutex.
  221 func (tf *tokenRefresher) Token() (*Token, error) {
  222     if tf.refreshToken == "" {
  223         return nil, errors.New("oauth2: token expired and refresh token is not set")
  224     }
  225 
  226     tk, err := retrieveToken(tf.ctx, tf.conf, url.Values{
  227         "grant_type":    {"refresh_token"},
  228         "refresh_token": {tf.refreshToken},
  229     })
  230 
  231     if err != nil {
  232         return nil, err
  233     }
  234     if tf.refreshToken != tk.RefreshToken {
  235         tf.refreshToken = tk.RefreshToken
  236     }
  237     return tk, err
  238 }
  239 
  240 // reuseTokenSource is a TokenSource that holds a single token in memory
  241 // and validates its expiry before each call to retrieve it with
  242 // Token. If it's expired, it will be auto-refreshed using the
  243 // new TokenSource.
  244 type reuseTokenSource struct {
  245     new TokenSource // called when t is expired.
  246 
  247     mu sync.Mutex // guards t
  248     t  *Token
  249 }
  250 
  251 // Token returns the current token if it's still valid, else will
  252 // refresh the current token (using r.Context for HTTP client
  253 // information) and return the new one.
  254 func (s *reuseTokenSource) Token() (*Token, error) {
  255     s.mu.Lock()
  256     defer s.mu.Unlock()
  257     if s.t.Valid() {
  258         return s.t, nil
  259     }
  260     t, err := s.new.Token()
  261     if err != nil {
  262         return nil, err
  263     }
  264     s.t = t
  265     return t, nil
  266 }
  267 
  268 // StaticTokenSource returns a TokenSource that always returns the same token.
  269 // Because the provided token t is never refreshed, StaticTokenSource is only
  270 // useful for tokens that never expire.
  271 func StaticTokenSource(t *Token) TokenSource {
  272     return staticTokenSource{t}
  273 }
  274 
  275 // staticTokenSource is a TokenSource that always returns the same Token.
  276 type staticTokenSource struct {
  277     t *Token
  278 }
  279 
  280 func (s staticTokenSource) Token() (*Token, error) {
  281     return s.t, nil
  282 }
  283 
  284 // HTTPClient is the context key to use with golang.org/x/net/context's
  285 // WithValue function to associate an *http.Client value with a context.
  286 var HTTPClient internal.ContextKey
  287 
  288 // NewClient creates an *http.Client from a Context and TokenSource.
  289 // The returned client is not valid beyond the lifetime of the context.
  290 //
  291 // As a special case, if src is nil, a non-OAuth2 client is returned
  292 // using the provided context. This exists to support related OAuth2
  293 // packages.
  294 func NewClient(ctx context.Context, src TokenSource) *http.Client {
  295     if src == nil {
  296         c, err := internal.ContextClient(ctx)
  297         if err != nil {
  298             return &http.Client{Transport: internal.ErrorTransport{err}}
  299         }
  300         return c
  301     }
  302     return &http.Client{
  303         Transport: &Transport{
  304             Base:   internal.ContextTransport(ctx),
  305             Source: ReuseTokenSource(nil, src),
  306         },
  307     }
  308 }
  309 
  310 // ReuseTokenSource returns a TokenSource which repeatedly returns the
  311 // same token as long as it's valid, starting with t.
  312 // When its cached token is invalid, a new token is obtained from src.
  313 //
  314 // ReuseTokenSource is typically used to reuse tokens from a cache
  315 // (such as a file on disk) between runs of a program, rather than
  316 // obtaining new tokens unnecessarily.
  317 //
  318 // The initial token t may be nil, in which case the TokenSource is
  319 // wrapped in a caching version if it isn't one already. This also
  320 // means it's always safe to wrap ReuseTokenSource around any other
  321 // TokenSource without adverse effects.
  322 func ReuseTokenSource(t *Token, src TokenSource) TokenSource {
  323     // Don't wrap a reuseTokenSource in itself. That would work,
  324     // but cause an unnecessary number of mutex operations.
  325     // Just build the equivalent one.
  326     if rt, ok := src.(*reuseTokenSource); ok {
  327         if t == nil {
  328             // Just use it directly.
  329             return rt
  330         }
  331         src = rt.new
  332     }
  333     return &reuseTokenSource{
  334         t:   t,
  335         new: src,
  336     }
  337 }