mirror of
https://github.com/golang/oauth2.git
synced 2025-07-21 00:00:09 +08:00
oauth2: fix expires_in for PayPal
PayPal returns "expires_in" token field as string, not integer. So, current implementation cannot unmarshal json of tokenJSON due type mismatch. This patch fixes the issue declaring field as interface{} in tokenJSON and performing type switch in "func (e *tokenJSON) expiry()". Related to issue #41. Change-Id: I69301e08c8a56fca049ca47906e32528cd22aef9 Reviewed-on: https://go-review.googlesource.com/6924 Reviewed-by: Andrew Gerrand <adg@golang.org>
This commit is contained in:
parent
54a4310f85
commit
6d4eed4495
20
oauth2.go
20
oauth2.go
@ -377,8 +377,8 @@ type tokenJSON struct {
|
|||||||
AccessToken string `json:"access_token"`
|
AccessToken string `json:"access_token"`
|
||||||
TokenType string `json:"token_type"`
|
TokenType string `json:"token_type"`
|
||||||
RefreshToken string `json:"refresh_token"`
|
RefreshToken string `json:"refresh_token"`
|
||||||
ExpiresIn int32 `json:"expires_in"`
|
ExpiresIn expirationTime `json:"expires_in"` // at least PayPal returns string, while most return number
|
||||||
Expires int32 `json:"expires"` // broken Facebook spelling of expires_in
|
Expires expirationTime `json:"expires"` // broken Facebook spelling of expires_in
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *tokenJSON) expiry() (t time.Time) {
|
func (e *tokenJSON) expiry() (t time.Time) {
|
||||||
@ -391,6 +391,22 @@ func (e *tokenJSON) expiry() (t time.Time) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type expirationTime int32
|
||||||
|
|
||||||
|
func (e *expirationTime) UnmarshalJSON(b []byte) error {
|
||||||
|
var n json.Number
|
||||||
|
err := json.Unmarshal(b, &n)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
i, err := n.Int64()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*e = expirationTime(i)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func condVal(v string) []string {
|
func condVal(v string) []string {
|
||||||
if v == "" {
|
if v == "" {
|
||||||
return nil
|
return nil
|
||||||
|
@ -5,12 +5,16 @@
|
|||||||
package oauth2
|
package oauth2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
@ -159,6 +163,56 @@ func TestExchangeRequest_JSONResponse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const day = 24 * time.Hour
|
||||||
|
|
||||||
|
func TestExchangeRequest_JSONResponse_Expiry(t *testing.T) {
|
||||||
|
seconds := int32(day.Seconds())
|
||||||
|
jsonNumberType := reflect.TypeOf(json.Number("0"))
|
||||||
|
for _, c := range []struct {
|
||||||
|
expires string
|
||||||
|
expect error
|
||||||
|
}{
|
||||||
|
{fmt.Sprintf(`"expires_in": %d`, seconds), nil},
|
||||||
|
{fmt.Sprintf(`"expires_in": "%d"`, seconds), nil}, // PayPal case
|
||||||
|
{fmt.Sprintf(`"expires": %d`, seconds), nil}, // Facebook case
|
||||||
|
{`"expires": false`, &json.UnmarshalTypeError{"bool", jsonNumberType}}, // wrong type
|
||||||
|
{`"expires": {}`, &json.UnmarshalTypeError{"object", jsonNumberType}}, // wrong type
|
||||||
|
{`"expires": "zzz"`, &strconv.NumError{"ParseInt", "zzz", strconv.ErrSyntax}}, // wrong value
|
||||||
|
} {
|
||||||
|
testExchangeRequest_JSONResponse_expiry(t, c.expires, c.expect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testExchangeRequest_JSONResponse_expiry(t *testing.T, exp string, expect error) {
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.Write([]byte(fmt.Sprintf(`{"access_token": "90d", "scope": "user", "token_type": "bearer", %s}`, exp)))
|
||||||
|
}))
|
||||||
|
defer ts.Close()
|
||||||
|
conf := newConf(ts.URL)
|
||||||
|
t1 := time.Now().Add(day)
|
||||||
|
tok, err := conf.Exchange(NoContext, "exchange-code")
|
||||||
|
t2 := time.Now().Add(day)
|
||||||
|
if err == nil && expect != nil {
|
||||||
|
t.Errorf("Incorrect state, conf.Exchange() should return an error: %v", expect)
|
||||||
|
} else if err != nil {
|
||||||
|
if reflect.DeepEqual(err, expect) {
|
||||||
|
t.Logf("Expected error: %v", err)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if !tok.Valid() {
|
||||||
|
t.Fatalf("Token invalid. Got: %#v", tok)
|
||||||
|
}
|
||||||
|
expiry := tok.Expiry
|
||||||
|
if expiry.Before(t1) || expiry.After(t2) {
|
||||||
|
t.Errorf("Unexpected value for Expiry: %v (shold be between %v and %v)", expiry, t1, t2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestExchangeRequest_BadResponse(t *testing.T) {
|
func TestExchangeRequest_BadResponse(t *testing.T) {
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user