From 12a5c0ada360a70e21de73f99f397dde5e83e1ee Mon Sep 17 00:00:00 2001 From: Eric Chiang Date: Thu, 3 Nov 2016 21:39:31 -0700 Subject: [PATCH] server: use seconds instead of nano seconds for expires_in and expiry --- server/handlers.go | 4 ++-- server/server_test.go | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/server/handlers.go b/server/handlers.go index 3bc49e7c..5bb5e904 100644 --- a/server/handlers.go +++ b/server/handlers.go @@ -439,7 +439,7 @@ func (s *Server) sendCodeResponse(w http.ResponseWriter, r *http.Request, authRe v.Set("token_type", "bearer") v.Set("id_token", idToken) v.Set("state", authReq.State) - v.Set("expires_in", strconv.Itoa(int(expiry.Sub(s.now())))) + v.Set("expires_in", strconv.Itoa(int(expiry.Sub(s.now()).Seconds()))) u.Fragment = v.Encode() } } @@ -637,7 +637,7 @@ func (s *Server) writeAccessToken(w http.ResponseWriter, idToken, refreshToken s }{ storage.NewID(), "bearer", - int(expiry.Sub(s.now())), + int(expiry.Sub(s.now()).Seconds()), refreshToken, idToken, } diff --git a/server/server_test.go b/server/server_test.go index d3ba1e3e..1f49a2bd 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -137,6 +137,18 @@ func TestOAuth2CodeFlow(t *testing.T) { clientSecret := "testclientsecret" requestedScopes := []string{oidc.ScopeOpenID, "email", "offline_access"} + t0 := time.Now().Round(time.Second) + + // Always have the time function used by the server return the same time so + // we can predict expected values of "expires_in" fields exactly. + now := func() time.Time { return t0 } + + // Used later when configuring test servers to set how long id_tokens will be valid for. + // + // The actual value of 30s is completely arbitrary. We just need to set a value + // so tests can compute the expected "expires_in" field. + idTokensValidFor := time.Second * 30 + tests := []struct { name string handleToken func(context.Context, *oidc.Provider, *oauth2.Config, *oauth2.Token) error @@ -154,6 +166,29 @@ func TestOAuth2CodeFlow(t *testing.T) { return nil }, }, + { + name: "verify id token and oauth2 token expiry", + handleToken: func(ctx context.Context, p *oidc.Provider, config *oauth2.Config, token *oauth2.Token) error { + expectedExpiry := now().Add(idTokensValidFor) + + if !token.Expiry.Round(time.Second).Equal(expectedExpiry) { + return fmt.Errorf("expected expired_in to be %s, got %s", expectedExpiry, token.Expiry) + } + + rawIDToken, ok := token.Extra("id_token").(string) + if !ok { + return fmt.Errorf("no id token found") + } + idToken, err := p.NewVerifier(ctx).Verify(rawIDToken) + if err != nil { + return fmt.Errorf("failed to verify id token: %v", err) + } + if !idToken.Expiry.Round(time.Second).Equal(expectedExpiry) { + return fmt.Errorf("expected id token expiry to be %s, got %s", expectedExpiry, token.Expiry) + } + return nil + }, + }, { name: "refresh token", handleToken: func(ctx context.Context, p *oidc.Provider, config *oauth2.Config, token *oauth2.Token) error { @@ -259,6 +294,8 @@ func TestOAuth2CodeFlow(t *testing.T) { httpServer, s := newTestServer(ctx, t, func(c *Config) { c.Issuer = c.Issuer + "/non-root-path" + c.Now = now + c.IDTokensValidFor = idTokensValidFor }) defer httpServer.Close()