forked from Mirrors/oauth2
commit
26b7d82d9d
55
cache.go
55
cache.go
|
@ -1,55 +0,0 @@
|
|||
// Copyright 2014 The oauth2 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 (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Cache represents a token cacher.
|
||||
type Cache interface {
|
||||
// Reads a cached token. It may return nil if none is cached.
|
||||
Read() (*Token, error)
|
||||
// Write writes a token to the cache.
|
||||
Write(*Token) error
|
||||
}
|
||||
|
||||
// NewFileCache creates a new file cache.
|
||||
func NewFileCache(filename string) (cache *FileCache) {
|
||||
return &FileCache{filename: filename}
|
||||
}
|
||||
|
||||
// FileCache represents a file based token cacher.
|
||||
type FileCache struct {
|
||||
filename string
|
||||
}
|
||||
|
||||
// Read reads the token from the cache file. If there exists no cache
|
||||
// file, it returns nil for the token.
|
||||
func (f *FileCache) Read() (token *Token, err error) {
|
||||
data, err := ioutil.ReadFile(f.filename)
|
||||
if os.IsNotExist(err) {
|
||||
// no token has cached before, skip reading
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = json.Unmarshal(data, &token); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Write writes a token to the specified file.
|
||||
func (f *FileCache) Write(token *Token) error {
|
||||
data, err := json.Marshal(token)
|
||||
if err == nil {
|
||||
err = ioutil.WriteFile(f.filename, data, 0644)
|
||||
}
|
||||
return err
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
// Copyright 2014 The oauth2 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 (
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var tokenBody = `{"access_token":"abc123","token_type":"Bearer","refresh_token":"def789","expiry":"0001-01-01T00:00:00Z"}`
|
||||
|
||||
func TestFileCacheReadNotExist(t *testing.T) {
|
||||
cache := NewFileCache("/path/that/doesnt/exist")
|
||||
token, err := cache.Read()
|
||||
if err != nil {
|
||||
t.Fatalf("NewFileCache shouldn't return an error for if cache file doesn't exist, but returned %v", err)
|
||||
}
|
||||
if token != nil {
|
||||
t.Fatalf("Token should be nil, but found %v", token)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewFileCache(t *testing.T) {
|
||||
f, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = f.WriteString(tokenBody)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cache := NewFileCache(f.Name())
|
||||
token, err := cache.Read()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if token.AccessToken != "abc123" {
|
||||
t.Fatalf("Cached access token is %v, expected to be abc123", token.AccessToken)
|
||||
}
|
||||
if token.RefreshToken != "def789" {
|
||||
t.Fatalf("Cached refresh token is %v, expected to be def789", token.RefreshToken)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileCacheWrite(t *testing.T) {
|
||||
dirName, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cache := NewFileCache(path.Join(dirName, "cache-file"))
|
||||
err = cache.Write(&Token{
|
||||
AccessToken: "abc123",
|
||||
TokenType: "Bearer",
|
||||
RefreshToken: "def789",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Cache write should have been succeeded succesfully, recieved %v", err)
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(cache.filename)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(data) != tokenBody {
|
||||
t.Fatalf("Written token is different than the expected, %v is found", data)
|
||||
}
|
||||
}
|
|
@ -51,23 +51,6 @@ func Example_config() {
|
|||
// start making authenticated requests.
|
||||
client := http.Client{Transport: t}
|
||||
client.Get("...")
|
||||
|
||||
// Alternatively, you can initiate a new transport
|
||||
// with tokens from a cache.
|
||||
cache := oauth2.NewFileCache("/path/to/file")
|
||||
// NewTransportWithCache will try to read the cached
|
||||
// token, if any error occurs, it returns the error.
|
||||
// If a token is available at the cache, initiates
|
||||
// a new transport authorized and authenticated with
|
||||
// the read token. If token expires, and a new access
|
||||
// token is retrieved, it writes the newly fetched
|
||||
// token to the cache.
|
||||
t, err = conf.NewTransportWithCache(cache)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
client = http.Client{Transport: t}
|
||||
client.Get("...")
|
||||
}
|
||||
|
||||
func Example_jWTConfig() {
|
||||
|
@ -95,18 +78,4 @@ func Example_jWTConfig() {
|
|||
// request will be made on the behalf of user@example.com.
|
||||
client = http.Client{Transport: conf.NewTransportWithUser("user@example.com")}
|
||||
client.Get("...")
|
||||
|
||||
// Alternatively you can iniate a transport with
|
||||
// a token read from the cache.
|
||||
// If the existing access token expires, and a new access token is
|
||||
// retrieved, the newly fetched token will be written to the cache.
|
||||
cache := oauth2.NewFileCache("/path/to/file")
|
||||
t, err := conf.NewTransportWithCache(cache)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
client = http.Client{Transport: t}
|
||||
// The following request will be authorized by the token
|
||||
// retrieved from the cache.
|
||||
client.Get("...")
|
||||
}
|
||||
|
|
|
@ -5,8 +5,9 @@ package google
|
|||
import (
|
||||
"strings"
|
||||
|
||||
"appengine"
|
||||
"github.com/golang/oauth2"
|
||||
|
||||
"appengine"
|
||||
)
|
||||
|
||||
// AppEngineConfig represents a configuration for an
|
||||
|
@ -28,12 +29,6 @@ func (c *AppEngineConfig) NewTransport() oauth2.Transport {
|
|||
return oauth2.NewAuthorizedTransport(c, nil)
|
||||
}
|
||||
|
||||
// NewTransport returns a token-caching transport that authorizes
|
||||
// the requests with the application's service account.
|
||||
func (c *AppEngineConfig) NewTransportWithCache(cache oauth2.Cache) (oauth2.Transport, error) {
|
||||
return oauth2.NewAuthorizedTransportWithCache(c, cache)
|
||||
}
|
||||
|
||||
// FetchToken fetches a new access token for the provided scopes.
|
||||
func (c *AppEngineConfig) FetchToken(existing *oauth2.Token) (*oauth2.Token, error) {
|
||||
token, expiry, err := appengine.AccessToken(c.context, strings.Join(c.scopes, " "))
|
||||
|
|
|
@ -14,7 +14,6 @@ import (
|
|||
type AppEngineConfig struct {
|
||||
context appengine.Context
|
||||
scopes []string
|
||||
cache oauth2.Cache
|
||||
}
|
||||
|
||||
// NewAppEngineConfig creates a new AppEngineConfig for the
|
||||
|
@ -29,12 +28,6 @@ func (c *AppEngineConfig) NewTransport() oauth2.Transport {
|
|||
return oauth2.NewAuthorizedTransport(c, nil)
|
||||
}
|
||||
|
||||
// NewTransport returns a token-caching transport that authorizes
|
||||
// the requests with the application's service account.
|
||||
func (c *AppEngineConfig) NewTransportWithCache(cache oauth2.Cache) (oauth2.Transport, error) {
|
||||
return oauth2.NewAuthorizedTransportWithCache(c, cache)
|
||||
}
|
||||
|
||||
// FetchToken fetches a new access token for the provided scopes.
|
||||
func (c *AppEngineConfig) FetchToken(existing *oauth2.Token) (*oauth2.Token, error) {
|
||||
token, expiry, err := appengine.AccessToken(c.context, strings.Join(c.scopes, " "))
|
||||
|
|
|
@ -45,23 +45,6 @@ func Example_webServer() {
|
|||
}
|
||||
client := http.Client{Transport: t}
|
||||
client.Get("...")
|
||||
|
||||
// Alternatively you can initiate a new transport
|
||||
// with a token from a cache.
|
||||
cache := oauth2.NewFileCache("/path/to/file")
|
||||
// NewTransportWithCache will try to read the cached
|
||||
// token, if any error occurs, it returns the error.
|
||||
// If a token is available at the cache, initiates
|
||||
// a new transport authorized and authenticated with
|
||||
// the read token. If token expires, and a new access
|
||||
// token is retrieved, it writes the newly fetched
|
||||
// token to the cache.
|
||||
t, err = config.NewTransportWithCache(cache)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
client = http.Client{Transport: t}
|
||||
client.Get("...")
|
||||
}
|
||||
|
||||
func Example_serviceAccounts() {
|
||||
|
@ -92,20 +75,6 @@ func Example_serviceAccounts() {
|
|||
// request will be made on the behalf of user@example.com.
|
||||
client = http.Client{Transport: config.NewTransportWithUser("user@example.com")}
|
||||
client.Get("...")
|
||||
|
||||
// Alternatively you can iniate a transport with
|
||||
// a token read from the cache.
|
||||
// If the existing access token expires, and a new access token is
|
||||
// retrieved, the newly fetched token will be written to the cache.
|
||||
cache := oauth2.NewFileCache("/path/to/file")
|
||||
t, err := config.NewTransportWithCache(cache)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
client = http.Client{Transport: t}
|
||||
// The following request will be authorized by the token
|
||||
// retrieved from the cache.
|
||||
client.Get("...")
|
||||
}
|
||||
|
||||
func Example_appEngine() {
|
||||
|
|
7
jwt.go
7
jwt.go
|
@ -70,13 +70,6 @@ func (c *JWTConfig) NewTransportWithUser(user string) Transport {
|
|||
return NewAuthorizedTransport(c, &Token{Subject: user})
|
||||
}
|
||||
|
||||
// NewTransportWithCache initializes a transport by reading the initial
|
||||
// token from the provided cache. If a token refreshing occurs, it
|
||||
// writes the newly fetched token back to the cache.
|
||||
func (c *JWTConfig) NewTransportWithCache(cache Cache) (Transport, error) {
|
||||
return NewAuthorizedTransportWithCache(c, cache)
|
||||
}
|
||||
|
||||
// fetchToken retrieves a new access token and updates the existing token
|
||||
// with the newly fetched credentials.
|
||||
func (c *JWTConfig) FetchToken(existing *Token) (token *Token, err error) {
|
||||
|
|
|
@ -153,13 +153,6 @@ func (c *Config) NewTransportWithCode(exchangeCode string) (Transport, error) {
|
|||
return NewAuthorizedTransport(c, token), nil
|
||||
}
|
||||
|
||||
// NewTransportWithCache initializes a transport by reading the initial
|
||||
// token from the provided cache. If a token refreshing occurs, it
|
||||
// writes the newly fetched token back to the cache.
|
||||
func (c *Config) NewTransportWithCache(cache Cache) (Transport, error) {
|
||||
return NewAuthorizedTransportWithCache(c, cache)
|
||||
}
|
||||
|
||||
// FetchToken retrieves a new access token and updates the existing token
|
||||
// with the newly fetched credentials. If existing token doesn't
|
||||
// contain a refresh token, it returns an error.
|
||||
|
|
|
@ -62,7 +62,7 @@ func TestExchangePayload(t *testing.T) {
|
|||
return nil, errors.New("no response")
|
||||
},
|
||||
}
|
||||
conf.Exchange("exchange-code")
|
||||
conf.exchange("exchange-code")
|
||||
}
|
||||
|
||||
func TestExchangingTransport(t *testing.T) {
|
||||
|
|
19
transport.go
19
transport.go
|
@ -76,9 +76,6 @@ type Transport interface {
|
|||
}
|
||||
|
||||
type authorizedTransport struct {
|
||||
// Cache to persist changes to the token that
|
||||
// authorizes the current transport.
|
||||
cache Cache
|
||||
fetcher TokenFetcher
|
||||
token *Token
|
||||
|
||||
|
@ -93,19 +90,6 @@ func NewAuthorizedTransport(fetcher TokenFetcher, token *Token) Transport {
|
|||
return &authorizedTransport{fetcher: fetcher, token: token}
|
||||
}
|
||||
|
||||
// NewAuthorizedTransportWithCache creates a new transport that uses
|
||||
// the provided token fetcher and cache. Before constructing the new
|
||||
// transport, it will try to read from the cache to see if there
|
||||
// is an existing token.
|
||||
func NewAuthorizedTransportWithCache(fetcher TokenFetcher, cache Cache) (transport Transport, err error) {
|
||||
var token *Token
|
||||
if token, err = cache.Read(); err != nil {
|
||||
return
|
||||
}
|
||||
transport = &authorizedTransport{fetcher: fetcher, cache: cache, token: token}
|
||||
return
|
||||
}
|
||||
|
||||
// RoundTrip authorizes the request with the existing token.
|
||||
// If token is expired, tries to refresh/fetch a new token.
|
||||
func (t *authorizedTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
|
||||
|
@ -176,9 +160,6 @@ func (t *authorizedTransport) RefreshToken() error {
|
|||
}
|
||||
|
||||
t.token = token
|
||||
if t.cache != nil {
|
||||
return t.cache.Write(token)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -7,17 +7,6 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
type mockCache struct{ token *Token }
|
||||
|
||||
func (m *mockCache) Read() (token *Token, err error) {
|
||||
return m.token, nil
|
||||
}
|
||||
|
||||
func (m *mockCache) Write(token *Token) error {
|
||||
m.token = token
|
||||
return nil
|
||||
}
|
||||
|
||||
type mockTokenFetcher struct{ token *Token }
|
||||
|
||||
func (f *mockTokenFetcher) FetchToken(existing *Token) (*Token, error) {
|
||||
|
@ -25,13 +14,10 @@ func (f *mockTokenFetcher) FetchToken(existing *Token) (*Token, error) {
|
|||
}
|
||||
|
||||
func TestInitialTokenRead(t *testing.T) {
|
||||
cache := &mockCache{token: &Token{
|
||||
AccessToken: "abc",
|
||||
}}
|
||||
tr, _ := NewAuthorizedTransportWithCache(nil, cache)
|
||||
tr := NewAuthorizedTransport(nil, &Token{AccessToken: "abc"})
|
||||
server := newMockServer(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("Authorization") != "Bearer abc" {
|
||||
t.Errorf("Transport doesn't read the token initially from the cache")
|
||||
t.Errorf("Transport doesn't set the Authorization header from the initial token")
|
||||
}
|
||||
})
|
||||
defer server.Close()
|
||||
|
@ -39,26 +25,24 @@ func TestInitialTokenRead(t *testing.T) {
|
|||
client.Get(server.URL)
|
||||
}
|
||||
|
||||
func TestTokenWrite(t *testing.T) {
|
||||
func TestTokenFetch(t *testing.T) {
|
||||
fetcher := &mockTokenFetcher{
|
||||
token: &Token{
|
||||
AccessToken: "abc",
|
||||
},
|
||||
}
|
||||
// cache with expired token
|
||||
cache := &mockCache{token: &Token{}}
|
||||
tr, _ := NewAuthorizedTransportWithCache(fetcher, cache)
|
||||
tr := NewAuthorizedTransport(fetcher, nil)
|
||||
server := newMockServer(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("Authorization") != "Bearer abc" {
|
||||
t.Errorf("Transport doesn't read the token initially from the cache")
|
||||
t.Errorf("Transport doesn't set the Authorization header from the fetched token")
|
||||
}
|
||||
})
|
||||
defer server.Close()
|
||||
|
||||
client := http.Client{Transport: tr}
|
||||
client.Get(server.URL)
|
||||
if cache.token.AccessToken != "abc" {
|
||||
t.Errorf("New token is not cached, found %v", cache.token)
|
||||
if tr.Token().AccessToken != "abc" {
|
||||
t.Errorf("New token is not set, found %v", tr.Token())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue