From 9887ac3be5006d42417f7e195be1d64d693d12c5 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Sun, 5 Apr 2015 10:51:17 -0400 Subject: [PATCH] Refactor cookie building and parsing Extracts buildCookieValue() and parseCookieValue() from OauthProxy.ServeHTTP() and adds tests for both. --- cookies.go | 31 +++++++++++++++++++++++++++++ cookies_test.go | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ oauthproxy.go | 28 +++++++++----------------- 3 files changed, 92 insertions(+), 19 deletions(-) diff --git a/cookies.go b/cookies.go index 0ae6a92..9605398 100644 --- a/cookies.go +++ b/cookies.go @@ -97,3 +97,34 @@ func decodeAccessToken(aes_cipher cipher.Block, encoded_access_token string) (st return string(encrypted_access_token), nil } + +func buildCookieValue(email string, aes_cipher cipher.Block, + access_token string) (string, error) { + if aes_cipher == nil { + return email, nil + } + + encoded_token, err := encodeAccessToken(aes_cipher, access_token) + if err != nil { + return email, fmt.Errorf( + "error encoding access token for %s: %s", email, err) + } + return email + "|" + encoded_token, nil +} + +func parseCookieValue(value string, aes_cipher cipher.Block) (email, user, + access_token string, err error) { + components := strings.Split(value, "|") + email = components[0] + user = strings.Split(email, "@")[0] + + if aes_cipher != nil && len(components) == 2 { + access_token, err = decodeAccessToken(aes_cipher, components[1]) + if err != nil { + err = fmt.Errorf( + "error decoding access token for %s: %s", + email, err) + } + } + return email, user, access_token, err +} diff --git a/cookies_test.go b/cookies_test.go index d5470d0..44696e8 100644 --- a/cookies_test.go +++ b/cookies_test.go @@ -3,6 +3,7 @@ package main import ( "crypto/aes" "github.com/bmizerany/assert" + "strings" "testing" ) @@ -21,3 +22,54 @@ func TestEncodeAndDecodeAccessToken(t *testing.T) { assert.NotEqual(t, access_token, encoded_token) assert.Equal(t, access_token, decoded_token) } + +func TestBuildCookieValueWithoutAccessToken(t *testing.T) { + value, err := buildCookieValue("michael.bland@gsa.gov", nil, "") + assert.Equal(t, nil, err) + assert.Equal(t, "michael.bland@gsa.gov", value) +} + +func TestBuildCookieValueWithAccessTokenAndNilCipher(t *testing.T) { + value, err := buildCookieValue("michael.bland@gsa.gov", nil, + "access token") + assert.Equal(t, nil, err) + assert.Equal(t, "michael.bland@gsa.gov", value) +} + +func TestParseCookieValueWithoutAccessToken(t *testing.T) { + email, user, access_token, err := parseCookieValue( + "michael.bland@gsa.gov", nil) + assert.Equal(t, nil, err) + assert.Equal(t, "michael.bland@gsa.gov", email) + assert.Equal(t, "michael.bland", user) + assert.Equal(t, "", access_token) +} + +func TestParseCookieValueWithAccessTokenAndNilCipher(t *testing.T) { + email, user, access_token, err := parseCookieValue( + "michael.bland@gsa.gov|access_token", nil) + assert.Equal(t, nil, err) + assert.Equal(t, "michael.bland@gsa.gov", email) + assert.Equal(t, "michael.bland", user) + assert.Equal(t, "", access_token) +} + +func TestBuildAndParseCookieValueWithAccessToken(t *testing.T) { + aes_cipher, err := aes.NewCipher([]byte("0123456789abcdef")) + assert.Equal(t, nil, err) + value, err := buildCookieValue("michael.bland@gsa.gov", aes_cipher, + "access_token") + assert.Equal(t, nil, err) + + prefix := "michael.bland@gsa.gov|" + if !strings.HasPrefix(value, prefix) { + t.Fatal("cookie value does not start with \"%s\": %s", + prefix, value) + } + + email, user, access_token, err := parseCookieValue(value, aes_cipher) + assert.Equal(t, nil, err) + assert.Equal(t, "michael.bland@gsa.gov", email) + assert.Equal(t, "michael.bland", user) + assert.Equal(t, "access_token", access_token) +} diff --git a/oauthproxy.go b/oauthproxy.go index 5b0fece..33f4698 100644 --- a/oauthproxy.go +++ b/oauthproxy.go @@ -425,20 +425,12 @@ func (p *OauthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { // set cookie, or deny if p.Validator(email) { log.Printf("%s authenticating %s completed", remoteAddr, email) - encoded_token := "" - if p.AesCipher != nil { - encoded_token, err = encodeAccessToken(p.AesCipher, access_token) - if err != nil { - log.Printf("error encoding access token: %s", err) - } - } - access_token = "" - - if encoded_token != "" { - p.SetCookie(rw, req, email+"|"+encoded_token) - } else { - p.SetCookie(rw, req, email) + value, err := buildCookieValue( + email, p.AesCipher, access_token) + if err != nil { + log.Printf(err.Error()) } + p.SetCookie(rw, req, value) http.Redirect(rw, req, redirect, 302) return } else { @@ -452,15 +444,13 @@ func (p *OauthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if err == nil { var value string value, ok = validateCookie(cookie, p.CookieSeed) - components := strings.Split(value, "|") - email = components[0] - if len(components) == 2 { - access_token, err = decodeAccessToken(p.AesCipher, components[1]) + if ok { + email, user, access_token, err = parseCookieValue( + value, p.AesCipher) if err != nil { - log.Printf("error decoding access token: %s", err) + log.Printf(err.Error()) } } - user = strings.Split(email, "@")[0] } }