internal: cap expires_in to MaxInt32

Fixes golang/oauth2#279

Change-Id: I29914e7995ec334a7474390a0ba96fe61deba6bb
Reviewed-on: https://go-review.googlesource.com/c/161962
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ross Light <light@google.com>
diff --git a/internal/token.go b/internal/token.go
index 955d5a0..83f7847 100644
--- a/internal/token.go
+++ b/internal/token.go
@@ -11,6 +11,7 @@
 	"fmt"
 	"io"
 	"io/ioutil"
+	"math"
 	"mime"
 	"net/http"
 	"net/url"
@@ -90,6 +91,9 @@
 	if err != nil {
 		return err
 	}
+	if i > math.MaxInt32 {
+		i = math.MaxInt32
+	}
 	*e = expirationTime(i)
 	return nil
 }
diff --git a/internal/token_test.go b/internal/token_test.go
index d8373c2..c54095a 100644
--- a/internal/token_test.go
+++ b/internal/token_test.go
@@ -6,7 +6,9 @@
 
 import (
 	"context"
+	"fmt"
 	"io"
+	"math"
 	"net/http"
 	"net/http/httptest"
 	"net/url"
@@ -62,3 +64,14 @@
 		t.Errorf("RetrieveToken (with cancelled context) = nil; want error")
 	}
 }
+
+func TestExpiresInUpperBound(t *testing.T) {
+	var e expirationTime
+	if err := e.UnmarshalJSON([]byte(fmt.Sprint(int64(math.MaxInt32) + 1))); err != nil {
+		t.Fatal(err)
+	}
+	const want = math.MaxInt32
+	if e != want {
+		t.Errorf("expiration time = %v; want %v", e, want)
+	}
+}