...

Source file src/golang.org/x/oauth2/clientcredentials/clientcredentials.go

Documentation: golang.org/x/oauth2/clientcredentials

     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 clientcredentials implements the OAuth2.0 "client credentials" token flow,
     6  // also known as the "two-legged OAuth 2.0".
     7  //
     8  // This should be used when the client is acting on its own behalf or when the client
     9  // is the resource owner. It may also be used when requesting access to protected
    10  // resources based on an authorization previously arranged with the authorization
    11  // server.
    12  //
    13  // See https://tools.ietf.org/html/rfc6749#section-4.4
    14  package clientcredentials // import "golang.org/x/oauth2/clientcredentials"
    15  
    16  import (
    17  	"context"
    18  	"fmt"
    19  	"net/http"
    20  	"net/url"
    21  	"strings"
    22  
    23  	"golang.org/x/oauth2"
    24  	"golang.org/x/oauth2/internal"
    25  )
    26  
    27  // Config describes a 2-legged OAuth2 flow, with both the
    28  // client application information and the server's endpoint URLs.
    29  type Config struct {
    30  	// ClientID is the application's ID.
    31  	ClientID string
    32  
    33  	// ClientSecret is the application's secret.
    34  	ClientSecret string
    35  
    36  	// TokenURL is the resource server's token endpoint
    37  	// URL. This is a constant specific to each server.
    38  	TokenURL string
    39  
    40  	// Scope specifies optional requested permissions.
    41  	Scopes []string
    42  
    43  	// EndpointParams specifies additional parameters for requests to the token endpoint.
    44  	EndpointParams url.Values
    45  
    46  	// AuthStyle optionally specifies how the endpoint wants the
    47  	// client ID & client secret sent. The zero value means to
    48  	// auto-detect.
    49  	AuthStyle oauth2.AuthStyle
    50  
    51  	// authStyleCache caches which auth style to use when Endpoint.AuthStyle is
    52  	// the zero value (AuthStyleAutoDetect).
    53  	authStyleCache internal.LazyAuthStyleCache
    54  }
    55  
    56  // Token uses client credentials to retrieve a token.
    57  //
    58  // The provided context optionally controls which HTTP client is used. See the oauth2.HTTPClient variable.
    59  func (c *Config) Token(ctx context.Context) (*oauth2.Token, error) {
    60  	return c.TokenSource(ctx).Token()
    61  }
    62  
    63  // Client returns an HTTP client using the provided token.
    64  // The token will auto-refresh as necessary.
    65  //
    66  // The provided context optionally controls which HTTP client
    67  // is returned. See the oauth2.HTTPClient variable.
    68  //
    69  // The returned Client and its Transport should not be modified.
    70  func (c *Config) Client(ctx context.Context) *http.Client {
    71  	return oauth2.NewClient(ctx, c.TokenSource(ctx))
    72  }
    73  
    74  // TokenSource returns a TokenSource that returns t until t expires,
    75  // automatically refreshing it as necessary using the provided context and the
    76  // client ID and client secret.
    77  //
    78  // Most users will use Config.Client instead.
    79  func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource {
    80  	source := &tokenSource{
    81  		ctx:  ctx,
    82  		conf: c,
    83  	}
    84  	return oauth2.ReuseTokenSource(nil, source)
    85  }
    86  
    87  type tokenSource struct {
    88  	ctx  context.Context
    89  	conf *Config
    90  }
    91  
    92  // Token refreshes the token by using a new client credentials request.
    93  // tokens received this way do not include a refresh token
    94  func (c *tokenSource) Token() (*oauth2.Token, error) {
    95  	v := url.Values{
    96  		"grant_type": {"client_credentials"},
    97  	}
    98  	if len(c.conf.Scopes) > 0 {
    99  		v.Set("scope", strings.Join(c.conf.Scopes, " "))
   100  	}
   101  	for k, p := range c.conf.EndpointParams {
   102  		// Allow grant_type to be overridden to allow interoperability with
   103  		// non-compliant implementations.
   104  		if _, ok := v[k]; ok && k != "grant_type" {
   105  			return nil, fmt.Errorf("oauth2: cannot overwrite parameter %q", k)
   106  		}
   107  		v[k] = p
   108  	}
   109  
   110  	tk, err := internal.RetrieveToken(c.ctx, c.conf.ClientID, c.conf.ClientSecret, c.conf.TokenURL, v, internal.AuthStyle(c.conf.AuthStyle), c.conf.authStyleCache.Get())
   111  	if err != nil {
   112  		if rErr, ok := err.(*internal.RetrieveError); ok {
   113  			return nil, (*oauth2.RetrieveError)(rErr)
   114  		}
   115  		return nil, err
   116  	}
   117  	t := &oauth2.Token{
   118  		AccessToken:  tk.AccessToken,
   119  		TokenType:    tk.TokenType,
   120  		RefreshToken: tk.RefreshToken,
   121  		Expiry:       tk.Expiry,
   122  	}
   123  	return t.WithExtra(tk.Raw), nil
   124  }
   125  

View as plain text