forked from Mirrors/oauth2
Don't provide a Transport interface but provide a http.RoundTripper implementation.
This commit is contained in:
parent
b314823c0b
commit
ee77246177
|
@ -27,16 +27,16 @@ func NewAppEngineConfig(context appengine.Context, scopes []string) *AppEngineCo
|
||||||
|
|
||||||
// NewTransport returns a transport that authorizes
|
// NewTransport returns a transport that authorizes
|
||||||
// the requests with the application's service account.
|
// the requests with the application's service account.
|
||||||
func (c *AppEngineConfig) NewTransport() oauth2.Transport {
|
func (c *AppEngineConfig) NewTransport() *oauth2.Transport {
|
||||||
if c.Transport != nil {
|
if c.Transport != nil {
|
||||||
return oauth2.NewAuthorizedTransport(c.Transport, c, nil)
|
return oauth2.NewTransport(c.Transport, c, nil)
|
||||||
}
|
}
|
||||||
transport := &urlfetch.Transport{
|
transport := &urlfetch.Transport{
|
||||||
Context: c.context,
|
Context: c.context,
|
||||||
Deadline: 0,
|
Deadline: 0,
|
||||||
AllowInvalidServerCertificate: false,
|
AllowInvalidServerCertificate: false,
|
||||||
}
|
}
|
||||||
return oauth2.NewAuthorizedTransport(transport, c, nil)
|
return oauth2.NewTransport(transport, c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchToken fetches a new access token for the provided scopes.
|
// FetchToken fetches a new access token for the provided scopes.
|
||||||
|
|
|
@ -24,8 +24,8 @@ func NewAppEngineConfig(context appengine.Context, scopes []string) *AppEngineCo
|
||||||
|
|
||||||
// NewTransport returns a transport that authorizes
|
// NewTransport returns a transport that authorizes
|
||||||
// the requests with the application's service account.
|
// the requests with the application's service account.
|
||||||
func (c *AppEngineConfig) NewTransport() oauth2.Transport {
|
func (c *AppEngineConfig) NewTransport() *oauth2.Transport {
|
||||||
return oauth2.NewAuthorizedTransport(http.DefaultTransport, c, nil)
|
return oauth2.NewTransport(http.DefaultTransport, c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchToken fetches a new access token for the provided scopes.
|
// FetchToken fetches a new access token for the provided scopes.
|
||||||
|
|
|
@ -60,8 +60,8 @@ func NewComputeEngineConfig(account string) *ComputeEngineConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTransport creates an authorized transport.
|
// NewTransport creates an authorized transport.
|
||||||
func (c *ComputeEngineConfig) NewTransport() oauth2.Transport {
|
func (c *ComputeEngineConfig) NewTransport() *oauth2.Transport {
|
||||||
return oauth2.NewAuthorizedTransport(http.DefaultTransport, c, nil)
|
return oauth2.NewTransport(http.DefaultTransport, c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchToken retrieves a new access token via metadata server.
|
// FetchToken retrieves a new access token via metadata server.
|
||||||
|
|
8
jwt.go
8
jwt.go
|
@ -78,14 +78,14 @@ type JWTConfig struct {
|
||||||
|
|
||||||
// NewTransport creates a transport that is authorize with the
|
// NewTransport creates a transport that is authorize with the
|
||||||
// parent JWT configuration.
|
// parent JWT configuration.
|
||||||
func (c *JWTConfig) NewTransport() Transport {
|
func (c *JWTConfig) NewTransport() *Transport {
|
||||||
return NewAuthorizedTransport(http.DefaultTransport, c, &Token{})
|
return NewTransport(http.DefaultTransport, c, &Token{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTransportWithUser creates a transport that is authorized by
|
// NewTransportWithUser creates a transport that is authorized by
|
||||||
// the client and impersonates the specified user.
|
// the client and impersonates the specified user.
|
||||||
func (c *JWTConfig) NewTransportWithUser(user string) Transport {
|
func (c *JWTConfig) NewTransportWithUser(user string) *Transport {
|
||||||
return NewAuthorizedTransport(http.DefaultTransport, c, &Token{Subject: user})
|
return NewTransport(http.DefaultTransport, c, &Token{Subject: user})
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetchToken retrieves a new access token and updates the existing token
|
// fetchToken retrieves a new access token and updates the existing token
|
||||||
|
|
10
oauth2.go
10
oauth2.go
|
@ -33,7 +33,7 @@ type tokenRespBody struct {
|
||||||
type TokenFetcher interface {
|
type TokenFetcher interface {
|
||||||
// FetchToken retrieves a new access token for the provider.
|
// FetchToken retrieves a new access token for the provider.
|
||||||
// If the implementation doesn't know how to retrieve a new token,
|
// If the implementation doesn't know how to retrieve a new token,
|
||||||
// it returns an error. Existing token could be nil.
|
// it returns an error. The existing token may be nil.
|
||||||
FetchToken(existing *Token) (*Token, error)
|
FetchToken(existing *Token) (*Token, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,20 +150,20 @@ func (c *Config) AuthCodeURL(state string) (authURL string) {
|
||||||
// t, _ := c.NewTransport()
|
// t, _ := c.NewTransport()
|
||||||
// t.SetToken(validToken)
|
// t.SetToken(validToken)
|
||||||
//
|
//
|
||||||
func (c *Config) NewTransport() Transport {
|
func (c *Config) NewTransport() *Transport {
|
||||||
return NewAuthorizedTransport(http.DefaultTransport, c, nil)
|
return NewTransport(http.DefaultTransport, c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTransportWithCode exchanges the OAuth 2.0 exchange code with
|
// NewTransportWithCode exchanges the OAuth 2.0 exchange code with
|
||||||
// the provider to fetch a new access token (and refresh token). Once
|
// the provider to fetch a new access token (and refresh token). Once
|
||||||
// it succesffully retrieves a new token, creates a new transport
|
// it succesffully retrieves a new token, creates a new transport
|
||||||
// authorized with it.
|
// authorized with it.
|
||||||
func (c *Config) NewTransportWithCode(exchangeCode string) (Transport, error) {
|
func (c *Config) NewTransportWithCode(exchangeCode string) (*Transport, error) {
|
||||||
token, err := c.Exchange(exchangeCode)
|
token, err := c.Exchange(exchangeCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return NewAuthorizedTransport(http.DefaultTransport, c, token), nil
|
return NewTransport(http.DefaultTransport, c, token), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchToken retrieves a new access token and updates the existing token
|
// FetchToken retrieves a new access token and updates the existing token
|
||||||
|
|
64
transport.go
64
transport.go
|
@ -52,52 +52,26 @@ func (t *Token) Expired() bool {
|
||||||
return t.Expiry.Before(time.Now())
|
return t.Expiry.Before(time.Now())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transport represents an authorized transport.
|
// Transport is an http.RoundTripper that makes OAuth 2.0 HTTP requests.
|
||||||
// Provides currently in-use user token and allows to set a token to
|
type Transport struct {
|
||||||
// be used. If token expires, it tries to fetch a new token,
|
|
||||||
// if possible. Token fetching is thread-safe. If two or more
|
|
||||||
// concurrent requests are being made with the same expired token,
|
|
||||||
// one of the requests will wait for the other to refresh
|
|
||||||
// the existing token.
|
|
||||||
type Transport interface {
|
|
||||||
// Authenticates the request with the existing token. If token is
|
|
||||||
// expired, tries to refresh/fetch a new token.
|
|
||||||
// Makes the request by delegating it to the default transport.
|
|
||||||
RoundTrip(*http.Request) (*http.Response, error)
|
|
||||||
|
|
||||||
// Returns the token authenticates the transport.
|
|
||||||
// This operation is thread-safe.
|
|
||||||
Token() *Token
|
|
||||||
|
|
||||||
// Sets a new token to authenticate the transport.
|
|
||||||
// This operation is thread-safe.
|
|
||||||
SetToken(token *Token)
|
|
||||||
|
|
||||||
// Refreshes the token if refresh is possible (such as in the
|
|
||||||
// presense of a refresh token). Returns an error if refresh is
|
|
||||||
// not possible. Refresh is thread-safe.
|
|
||||||
RefreshToken() error
|
|
||||||
}
|
|
||||||
|
|
||||||
type authorizedTransport struct {
|
|
||||||
fetcher TokenFetcher
|
fetcher TokenFetcher
|
||||||
token *Token
|
|
||||||
origTransport http.RoundTripper
|
origTransport http.RoundTripper
|
||||||
|
|
||||||
// Mutex to protect token during auto refreshments.
|
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
|
token *Token
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAuthorizedTransport creates a transport that uses the provided
|
// NewTransport creates a new Transport that uses the provided
|
||||||
// token fetcher to retrieve new tokens if there is no access token
|
// token fetcher as token retrieving strategy. It authenticates
|
||||||
// provided or it is expired.
|
// the requests and delegates origTransport to make the actual requests.
|
||||||
func NewAuthorizedTransport(origTransport http.RoundTripper, fetcher TokenFetcher, token *Token) Transport {
|
func NewTransport(origTransport http.RoundTripper, fetcher TokenFetcher, token *Token) *Transport {
|
||||||
return &authorizedTransport{origTransport: origTransport, fetcher: fetcher, token: token}
|
return &Transport{origTransport: origTransport, fetcher: fetcher, token: token}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RoundTrip authorizes the request with the existing token.
|
// RoundTrip authorizes and authenticates the request with an
|
||||||
// If token is expired, tries to refresh/fetch a new token.
|
// access token. If no token exists or token is expired,
|
||||||
func (t *authorizedTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
|
// tries to refresh/fetch a new token.
|
||||||
|
func (t *Transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
|
||||||
token := t.Token()
|
token := t.Token()
|
||||||
|
|
||||||
if token == nil || token.Expired() {
|
if token == nil || token.Expired() {
|
||||||
|
@ -126,14 +100,15 @@ func (t *authorizedTransport) RoundTrip(req *http.Request) (resp *http.Response,
|
||||||
return t.origTransport.RoundTrip(req)
|
return t.origTransport.RoundTrip(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Token returns the existing token that authorizes the Transport.
|
// Token returns the token that authorizes and
|
||||||
func (t *authorizedTransport) Token() *Token {
|
// authenticates the transport.
|
||||||
|
func (t *Transport) Token() *Token {
|
||||||
t.mu.RLock()
|
t.mu.RLock()
|
||||||
defer t.mu.RUnlock()
|
defer t.mu.RUnlock()
|
||||||
if t.token == nil {
|
if t.token == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
token := &Token{
|
return &Token{
|
||||||
AccessToken: t.token.AccessToken,
|
AccessToken: t.token.AccessToken,
|
||||||
TokenType: t.token.TokenType,
|
TokenType: t.token.TokenType,
|
||||||
RefreshToken: t.token.RefreshToken,
|
RefreshToken: t.token.RefreshToken,
|
||||||
|
@ -141,21 +116,20 @@ func (t *authorizedTransport) Token() *Token {
|
||||||
Extra: t.token.Extra,
|
Extra: t.token.Extra,
|
||||||
Subject: t.token.Subject,
|
Subject: t.token.Subject,
|
||||||
}
|
}
|
||||||
return token
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetToken sets a token to the transport in a thread-safe way.
|
// SetToken sets a token to the transport in a thread-safe way.
|
||||||
func (t *authorizedTransport) SetToken(token *Token) {
|
func (t *Transport) SetToken(v *Token) {
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
defer t.mu.Unlock()
|
defer t.mu.Unlock()
|
||||||
|
|
||||||
t.token = token
|
t.token = v
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefreshToken retrieves a new token, if a refreshing/fetching
|
// RefreshToken retrieves a new token, if a refreshing/fetching
|
||||||
// method is known and required credentials are presented
|
// method is known and required credentials are presented
|
||||||
// (such as a refresh token).
|
// (such as a refresh token).
|
||||||
func (t *authorizedTransport) RefreshToken() error {
|
func (t *Transport) RefreshToken() error {
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
defer t.mu.Unlock()
|
defer t.mu.Unlock()
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ func (f *mockTokenFetcher) FetchToken(existing *Token) (*Token, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInitialTokenRead(t *testing.T) {
|
func TestInitialTokenRead(t *testing.T) {
|
||||||
tr := NewAuthorizedTransport(http.DefaultTransport, nil, &Token{AccessToken: "abc"})
|
tr := NewTransport(http.DefaultTransport, nil, &Token{AccessToken: "abc"})
|
||||||
server := newMockServer(func(w http.ResponseWriter, r *http.Request) {
|
server := newMockServer(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Header.Get("Authorization") != "Bearer abc" {
|
if r.Header.Get("Authorization") != "Bearer abc" {
|
||||||
t.Errorf("Transport doesn't set the Authorization header from the initial token")
|
t.Errorf("Transport doesn't set the Authorization header from the initial token")
|
||||||
|
@ -31,7 +31,7 @@ func TestTokenFetch(t *testing.T) {
|
||||||
AccessToken: "abc",
|
AccessToken: "abc",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
tr := NewAuthorizedTransport(http.DefaultTransport, fetcher, nil)
|
tr := NewTransport(http.DefaultTransport, fetcher, nil)
|
||||||
server := newMockServer(func(w http.ResponseWriter, r *http.Request) {
|
server := newMockServer(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Header.Get("Authorization") != "Bearer abc" {
|
if r.Header.Get("Authorization") != "Bearer abc" {
|
||||||
t.Errorf("Transport doesn't set the Authorization header from the fetched token")
|
t.Errorf("Transport doesn't set the Authorization header from the fetched token")
|
||||||
|
|
Loading…
Reference in New Issue