forked from Mirrors/oauth2
remove cache
This commit is contained in:
parent
e62c791d44
commit
93ad3f4a9e
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.
|
// start making authenticated requests.
|
||||||
client := http.Client{Transport: t}
|
client := http.Client{Transport: t}
|
||||||
client.Get("...")
|
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() {
|
func Example_jWTConfig() {
|
||||||
|
@ -95,18 +78,4 @@ func Example_jWTConfig() {
|
||||||
// request will be made on the behalf of user@example.com.
|
// request will be made on the behalf of user@example.com.
|
||||||
client = http.Client{Transport: conf.NewTransportWithUser("user@example.com")}
|
client = http.Client{Transport: conf.NewTransportWithUser("user@example.com")}
|
||||||
client.Get("...")
|
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 (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"appengine"
|
|
||||||
"github.com/golang/oauth2"
|
"github.com/golang/oauth2"
|
||||||
|
|
||||||
|
"appengine"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AppEngineConfig represents a configuration for an
|
// AppEngineConfig represents a configuration for an
|
||||||
|
@ -28,12 +29,6 @@ func (c *AppEngineConfig) NewTransport() oauth2.Transport {
|
||||||
return oauth2.NewAuthorizedTransport(c, nil)
|
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.
|
// FetchToken fetches a new access token for the provided scopes.
|
||||||
func (c *AppEngineConfig) FetchToken(existing *oauth2.Token) (*oauth2.Token, error) {
|
func (c *AppEngineConfig) FetchToken(existing *oauth2.Token) (*oauth2.Token, error) {
|
||||||
token, expiry, err := appengine.AccessToken(c.context, strings.Join(c.scopes, " "))
|
token, expiry, err := appengine.AccessToken(c.context, strings.Join(c.scopes, " "))
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
type AppEngineConfig struct {
|
type AppEngineConfig struct {
|
||||||
context appengine.Context
|
context appengine.Context
|
||||||
scopes []string
|
scopes []string
|
||||||
cache oauth2.Cache
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAppEngineConfig creates a new AppEngineConfig for the
|
// NewAppEngineConfig creates a new AppEngineConfig for the
|
||||||
|
@ -29,12 +28,6 @@ func (c *AppEngineConfig) NewTransport() oauth2.Transport {
|
||||||
return oauth2.NewAuthorizedTransport(c, nil)
|
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.
|
// FetchToken fetches a new access token for the provided scopes.
|
||||||
func (c *AppEngineConfig) FetchToken(existing *oauth2.Token) (*oauth2.Token, error) {
|
func (c *AppEngineConfig) FetchToken(existing *oauth2.Token) (*oauth2.Token, error) {
|
||||||
token, expiry, err := appengine.AccessToken(c.context, strings.Join(c.scopes, " "))
|
token, expiry, err := appengine.AccessToken(c.context, strings.Join(c.scopes, " "))
|
||||||
|
|
|
@ -45,23 +45,6 @@ func Example_webServer() {
|
||||||
}
|
}
|
||||||
client := http.Client{Transport: t}
|
client := http.Client{Transport: t}
|
||||||
client.Get("...")
|
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() {
|
func Example_serviceAccounts() {
|
||||||
|
@ -92,20 +75,6 @@ func Example_serviceAccounts() {
|
||||||
// request will be made on the behalf of user@example.com.
|
// request will be made on the behalf of user@example.com.
|
||||||
client = http.Client{Transport: config.NewTransportWithUser("user@example.com")}
|
client = http.Client{Transport: config.NewTransportWithUser("user@example.com")}
|
||||||
client.Get("...")
|
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() {
|
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})
|
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
|
// fetchToken retrieves a new access token and updates the existing token
|
||||||
// with the newly fetched credentials.
|
// with the newly fetched credentials.
|
||||||
func (c *JWTConfig) FetchToken(existing *Token) (token *Token, err error) {
|
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
|
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
|
// FetchToken retrieves a new access token and updates the existing token
|
||||||
// with the newly fetched credentials. If existing token doesn't
|
// with the newly fetched credentials. If existing token doesn't
|
||||||
// contain a refresh token, it returns an error.
|
// contain a refresh token, it returns an error.
|
||||||
|
|
|
@ -62,7 +62,7 @@ func TestExchangePayload(t *testing.T) {
|
||||||
return nil, errors.New("no response")
|
return nil, errors.New("no response")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
conf.Exchange("exchange-code")
|
conf.exchange("exchange-code")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExchangingTransport(t *testing.T) {
|
func TestExchangingTransport(t *testing.T) {
|
||||||
|
|
19
transport.go
19
transport.go
|
@ -76,9 +76,6 @@ type Transport interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type authorizedTransport struct {
|
type authorizedTransport struct {
|
||||||
// Cache to persist changes to the token that
|
|
||||||
// authorizes the current transport.
|
|
||||||
cache Cache
|
|
||||||
fetcher TokenFetcher
|
fetcher TokenFetcher
|
||||||
token *Token
|
token *Token
|
||||||
|
|
||||||
|
@ -93,19 +90,6 @@ func NewAuthorizedTransport(fetcher TokenFetcher, token *Token) Transport {
|
||||||
return &authorizedTransport{fetcher: fetcher, token: token}
|
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.
|
// RoundTrip authorizes the request with the existing token.
|
||||||
// If token is expired, tries to refresh/fetch a new token.
|
// If token is expired, tries to refresh/fetch a new token.
|
||||||
func (t *authorizedTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
|
func (t *authorizedTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
|
||||||
|
@ -176,9 +160,6 @@ func (t *authorizedTransport) RefreshToken() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
t.token = token
|
t.token = token
|
||||||
if t.cache != nil {
|
|
||||||
return t.cache.Write(token)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,17 +7,6 @@ import (
|
||||||
"time"
|
"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 }
|
type mockTokenFetcher struct{ token *Token }
|
||||||
|
|
||||||
func (f *mockTokenFetcher) FetchToken(existing *Token) (*Token, error) {
|
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) {
|
func TestInitialTokenRead(t *testing.T) {
|
||||||
cache := &mockCache{token: &Token{
|
tr := NewAuthorizedTransport(nil, &Token{AccessToken: "abc"})
|
||||||
AccessToken: "abc",
|
|
||||||
}}
|
|
||||||
tr, _ := NewAuthorizedTransportWithCache(nil, cache)
|
|
||||||
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 read the token initially from the cache")
|
t.Errorf("Transport doesn't set the Authorization header from the initial token")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
@ -39,26 +25,24 @@ func TestInitialTokenRead(t *testing.T) {
|
||||||
client.Get(server.URL)
|
client.Get(server.URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTokenWrite(t *testing.T) {
|
func TestTokenFetch(t *testing.T) {
|
||||||
fetcher := &mockTokenFetcher{
|
fetcher := &mockTokenFetcher{
|
||||||
token: &Token{
|
token: &Token{
|
||||||
AccessToken: "abc",
|
AccessToken: "abc",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
// cache with expired token
|
tr := NewAuthorizedTransport(fetcher, nil)
|
||||||
cache := &mockCache{token: &Token{}}
|
|
||||||
tr, _ := NewAuthorizedTransportWithCache(fetcher, cache)
|
|
||||||
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 read the token initially from the cache")
|
t.Errorf("Transport doesn't set the Authorization header from the fetched token")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
client := http.Client{Transport: tr}
|
client := http.Client{Transport: tr}
|
||||||
client.Get(server.URL)
|
client.Get(server.URL)
|
||||||
if cache.token.AccessToken != "abc" {
|
if tr.Token().AccessToken != "abc" {
|
||||||
t.Errorf("New token is not cached, found %v", cache.token)
|
t.Errorf("New token is not set, found %v", tr.Token())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue