4444var defaultTestOpts = []option.ClientOption {
4545 option .WithCredentialsFile ("../testdata/service_account.json" ),
4646}
47+ var testClock = & mockClock {now : time .Now ()}
4748
4849func TestMain (m * testing.M ) {
4950 var (
@@ -74,6 +75,7 @@ func TestMain(m *testing.M) {
7475
7576 ks = & fileKeySource {FilePath : "../testdata/public_certs.json" }
7677 }
78+
7779 client , err = NewClient (ctx , & internal.AuthConfig {
7880 Creds : creds ,
7981 Opts : opts ,
@@ -83,6 +85,7 @@ func TestMain(m *testing.M) {
8385 log .Fatalln (err )
8486 }
8587 client .keySource = ks
88+ client .clock = testClock
8689
8790 testGetUserResponse , err = ioutil .ReadFile ("../testdata/get_user.json" )
8891 if err != nil {
@@ -289,6 +292,35 @@ func TestVerifyIDToken(t *testing.T) {
289292 }
290293}
291294
295+ func TestVerifyIDTokenClockSkew (t * testing.T ) {
296+ now := testClock .Now ().Unix ()
297+ cases := []struct {
298+ name string
299+ token string
300+ }{
301+ {"FutureToken" , getIDToken (mockIDTokenPayload {"iat" : now + clockSkewSeconds - 1 })},
302+ {"ExpiredToken" , getIDToken (mockIDTokenPayload {
303+ "iat" : now - 1000 ,
304+ "exp" : now - clockSkewSeconds + 1 ,
305+ })},
306+ }
307+
308+ for _ , tc := range cases {
309+ t .Run (tc .name , func (t * testing.T ) {
310+ ft , err := client .VerifyIDToken (ctx , tc .token )
311+ if err != nil {
312+ t .Errorf ("VerifyIDToken(%q) = (%q, %v); want = (token, nil)" , tc .name , ft , err )
313+ }
314+ if ft .Claims ["admin" ] != true {
315+ t .Errorf ("Claims['admin'] = %v; want = true" , ft .Claims ["admin" ])
316+ }
317+ if ft .UID != ft .Subject {
318+ t .Errorf ("UID = %q; Sub = %q; want UID = Sub" , ft .UID , ft .Subject )
319+ }
320+ })
321+ }
322+ }
323+
292324func TestVerifyIDTokenInvalidSignature (t * testing.T ) {
293325 parts := strings .Split (testIDToken , "." )
294326 token := fmt .Sprintf ("%s:%s:invalidsignature" , parts [0 ], parts [1 ])
@@ -298,7 +330,7 @@ func TestVerifyIDTokenInvalidSignature(t *testing.T) {
298330}
299331
300332func TestVerifyIDTokenError (t * testing.T ) {
301- now := time .Now ().Unix ()
333+ now := testClock .Now ().Unix ()
302334 cases := []struct {
303335 name string
304336 token string
@@ -310,10 +342,10 @@ func TestVerifyIDTokenError(t *testing.T) {
310342 {"EmptySubject" , getIDToken (mockIDTokenPayload {"sub" : "" })},
311343 {"IntSubject" , getIDToken (mockIDTokenPayload {"sub" : 10 })},
312344 {"LongSubject" , getIDToken (mockIDTokenPayload {"sub" : strings .Repeat ("a" , 129 )})},
313- {"FutureToken" , getIDToken (mockIDTokenPayload {"iat" : now + 1000 })},
345+ {"FutureToken" , getIDToken (mockIDTokenPayload {"iat" : now + clockSkewSeconds + 1 })},
314346 {"ExpiredToken" , getIDToken (mockIDTokenPayload {
315347 "iat" : now - 1000 ,
316- "exp" : now - 100 ,
348+ "exp" : now - clockSkewSeconds - 1 ,
317349 })},
318350 {"EmptyToken" , "" },
319351 {"BadFormatToken" , "foobar" },
@@ -419,6 +451,14 @@ func verifyCustomToken(ctx context.Context, token string, expected map[string]in
419451 t .Errorf ("Subject: %q; want: %q" , payload .Sub , email )
420452 }
421453
454+ now := testClock .Now ().Unix ()
455+ if payload .Exp != now + 3600 {
456+ t .Errorf ("Exp: %d; want: %d" , payload .Exp , now + 3600 )
457+ }
458+ if payload .Iat != now {
459+ t .Errorf ("Iat: %d; want: %d" , payload .Iat , now )
460+ }
461+
422462 for k , v := range expected {
423463 if payload .Claims [k ] != v {
424464 t .Errorf ("Claim[%q]: %v; want: %v" , k , payload .Claims [k ], v )
@@ -434,8 +474,8 @@ func getIDTokenWithKid(kid string, p mockIDTokenPayload) string {
434474 pCopy := mockIDTokenPayload {
435475 "aud" : client .projectID ,
436476 "iss" : "https://securetoken.google.com/" + client .projectID ,
437- "iat" : time .Now ().Unix () - 100 ,
438- "exp" : time .Now ().Unix () + 3600 ,
477+ "iat" : testClock .Now ().Unix () - 100 ,
478+ "exp" : testClock .Now ().Unix () + 3600 ,
439479 "sub" : "1234567890" ,
440480 "admin" : true ,
441481 }
0 commit comments