diff --git a/token.go b/token.go index e04a2dd..9852ceb 100644 --- a/token.go +++ b/token.go @@ -10,6 +10,11 @@ import ( "time" ) +// expiryDelta determines how earlier a token should be considered +// expired than its actual expiration time. It is used to avoid late +// expirations due to client-server time mismatches. +const expiryDelta = 10 * time.Second + // Token represents the crendentials used to authorize // the requests to access protected resources on the OAuth 2.0 // provider's backend. @@ -90,7 +95,7 @@ func (t *Token) expired() bool { if t.Expiry.IsZero() { return false } - return t.Expiry.Before(time.Now()) + return t.Expiry.Add(-expiryDelta).Before(time.Now()) } // Valid reports whether t is non-nil, has an AccessToken, and is not expired. diff --git a/token_test.go b/token_test.go index 74d6366..739eeb2 100644 --- a/token_test.go +++ b/token_test.go @@ -4,7 +4,10 @@ package oauth2 -import "testing" +import ( + "testing" + "time" +) func TestTokenExtra(t *testing.T) { type testCase struct { @@ -28,3 +31,20 @@ func TestTokenExtra(t *testing.T) { } } } + +func TestTokenExpiry(t *testing.T) { + now := time.Now() + cases := []struct { + name string + tok *Token + want bool + }{ + {name: "12 seconds", tok: &Token{Expiry: now.Add(12 * time.Second)}, want: false}, + {name: "10 seconds", tok: &Token{Expiry: now.Add(expiryDelta)}, want: true}, + } + for _, tc := range cases { + if got, want := tc.tok.expired(), tc.want; got != want { + t.Errorf("expired (%q) = %v; want %v", tc.name, got, want) + } + } +}