From c668d6f957a724b4a3a79a84dd9d6600a2a911c7 Mon Sep 17 00:00:00 2001 From: Greg Steuck Date: Mon, 12 Jul 2021 20:49:17 -0700 Subject: dashboard/app: control time externally from api.go This way the tested code is independent of the time passage and the tests are reliable. --- dashboard/app/api.go | 2 +- dashboard/app/auth.go | 7 ++++--- dashboard/app/auth_test.go | 19 +++++++++++-------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/dashboard/app/api.go b/dashboard/app/api.go index 8ce6658cf..dad31c3df 100644 --- a/dashboard/app/api.go +++ b/dashboard/app/api.go @@ -105,7 +105,7 @@ func handleAPI(c context.Context, r *http.Request) (reply interface{}, err error method := r.PostFormValue("method") log.Infof(c, "api %q from %q", method, client) auth := makeAuthEndpoint(googleTokenInfoEndpoint) - subj, err := auth.determineAuthSubj(r.Header["Authorization"]) + subj, err := auth.determineAuthSubj(timeNow(c), r.Header["Authorization"]) if err != nil { return nil, err } diff --git a/dashboard/app/auth.go b/dashboard/app/auth.go index 25f20b10d..42d59e6ee 100644 --- a/dashboard/app/auth.go +++ b/dashboard/app/auth.go @@ -100,8 +100,9 @@ func (auth *authEndpoint) queryTokenInfo(tokenValue string) (*jwtClaims, error) // Returns the verified subject value based on the provided header // value or "" if it can't be determined. A valid result starts with -// oauthMagic. -func (auth *authEndpoint) determineAuthSubj(authHeader []string) (string, error) { +// oauthMagic. The now parameter is the current time to compare the +// claims against. +func (auth *authEndpoint) determineAuthSubj(now time.Time, authHeader []string) (string, error) { if len(authHeader) != 1 || !strings.HasPrefix(authHeader[0], "Bearer") { // This is a normal case when the client uses a password. return "", nil @@ -117,7 +118,7 @@ func (auth *authEndpoint) determineAuthSubj(authHeader []string) (string, error) err := fmt.Errorf("unexpected audience %v %v", claims.Audience, claims) return "", err } - if claims.Expiration.Before(time.Now()) { + if claims.Expiration.Before(now) { err := fmt.Errorf("token past expiration %v", claims.Expiration) return "", err } diff --git a/dashboard/app/auth_test.go b/dashboard/app/auth_test.go index 18d6a8b82..ae52721e7 100644 --- a/dashboard/app/auth_test.go +++ b/dashboard/app/auth_test.go @@ -32,15 +32,16 @@ func reponseFor(t *testing.T, claims jwtClaims) (*httptest.Server, authEndpoint) } func TestBearerValid(t *testing.T) { + tm := time.Now() magic := "ValidSubj" ts, dut := reponseFor(t, jwtClaims{ Subject: magic, Audience: dashapi.DashboardAudience, - Expiration: time.Now().AddDate(0, 0, 1), + Expiration: tm.AddDate(0, 0, 1), }) defer ts.Close() - got, err := dut.determineAuthSubj([]string{"Bearer x"}) + got, err := dut.determineAuthSubj(tm, []string{"Bearer x"}) if err != nil { t.Errorf("Unexpected error %v", err) } @@ -50,28 +51,30 @@ func TestBearerValid(t *testing.T) { } func TestBearerWrongAudience(t *testing.T) { + tm := time.Now() ts, dut := reponseFor(t, jwtClaims{ Subject: "irrelevant", - Expiration: time.Now().AddDate(0, 0, 1), + Expiration: tm.AddDate(0, 0, 1), Audience: "junk", }) defer ts.Close() - _, err := dut.determineAuthSubj([]string{"Bearer x"}) + _, err := dut.determineAuthSubj(tm, []string{"Bearer x"}) if !strings.HasPrefix(err.Error(), "unexpected audience") { t.Fatalf("Unexpected error %v", err) } } func TestBearerExpired(t *testing.T) { + tm := time.Now() ts, dut := reponseFor(t, jwtClaims{ Subject: "irrelevant", - Expiration: time.Now().AddDate(0, 0, -1), + Expiration: tm.AddDate(0, 0, -1), Audience: dashapi.DashboardAudience, }) defer ts.Close() - _, err := dut.determineAuthSubj([]string{"Bearer x"}) + _, err := dut.determineAuthSubj(tm, []string{"Bearer x"}) if !strings.HasPrefix(err.Error(), "token past expiration") { t.Fatalf("Unexpected error %v", err) } @@ -80,7 +83,7 @@ func TestBearerExpired(t *testing.T) { func TestMissingHeader(t *testing.T) { ts, dut := reponseFor(t, jwtClaims{}) defer ts.Close() - got, err := dut.determineAuthSubj([]string{}) + got, err := dut.determineAuthSubj(time.Now(), []string{}) if err != nil || got != "" { t.Errorf("Unexpected error %v %v", got, err) } @@ -89,7 +92,7 @@ func TestMissingHeader(t *testing.T) { func TestBadHeader(t *testing.T) { ts, dut := reponseFor(t, jwtClaims{}) defer ts.Close() - got, err := dut.determineAuthSubj([]string{"bad"}) + got, err := dut.determineAuthSubj(time.Now(), []string{"bad"}) if err != nil || got != "" { t.Errorf("Unexpected error %v %v", got, err) } -- cgit mrf-deployment