Refactor cookie building and parsing
Extracts buildCookieValue() and parseCookieValue() from OauthProxy.ServeHTTP() and adds tests for both.
This commit is contained in:
		
							parent
							
								
									cf79fd9e4c
								
							
						
					
					
						commit
						9887ac3be5
					
				
							
								
								
									
										31
									
								
								cookies.go
								
								
								
								
							
							
						
						
									
										31
									
								
								cookies.go
								
								
								
								
							|  | @ -97,3 +97,34 @@ func decodeAccessToken(aes_cipher cipher.Block, encoded_access_token string) (st | ||||||
| 
 | 
 | ||||||
| 	return string(encrypted_access_token), nil | 	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 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ package main | ||||||
| import ( | import ( | ||||||
| 	"crypto/aes" | 	"crypto/aes" | ||||||
| 	"github.com/bmizerany/assert" | 	"github.com/bmizerany/assert" | ||||||
|  | 	"strings" | ||||||
| 	"testing" | 	"testing" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -21,3 +22,54 @@ func TestEncodeAndDecodeAccessToken(t *testing.T) { | ||||||
| 	assert.NotEqual(t, access_token, encoded_token) | 	assert.NotEqual(t, access_token, encoded_token) | ||||||
| 	assert.Equal(t, access_token, decoded_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) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -425,20 +425,12 @@ func (p *OauthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { | ||||||
| 		// set cookie, or deny
 | 		// set cookie, or deny
 | ||||||
| 		if p.Validator(email) { | 		if p.Validator(email) { | ||||||
| 			log.Printf("%s authenticating %s completed", remoteAddr, email) | 			log.Printf("%s authenticating %s completed", remoteAddr, email) | ||||||
| 			encoded_token := "" | 			value, err := buildCookieValue( | ||||||
| 			if p.AesCipher != nil { | 				email, p.AesCipher, access_token) | ||||||
| 				encoded_token, err = encodeAccessToken(p.AesCipher, access_token) |  | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 					log.Printf("error encoding access token: %s", err) | 				log.Printf(err.Error()) | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			access_token = "" |  | ||||||
| 
 |  | ||||||
| 			if encoded_token != "" { |  | ||||||
| 				p.SetCookie(rw, req, email+"|"+encoded_token) |  | ||||||
| 			} else { |  | ||||||
| 				p.SetCookie(rw, req, email) |  | ||||||
| 			} | 			} | ||||||
|  | 			p.SetCookie(rw, req, value) | ||||||
| 			http.Redirect(rw, req, redirect, 302) | 			http.Redirect(rw, req, redirect, 302) | ||||||
| 			return | 			return | ||||||
| 		} else { | 		} else { | ||||||
|  | @ -452,15 +444,13 @@ func (p *OauthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { | ||||||
| 		if err == nil { | 		if err == nil { | ||||||
| 			var value string | 			var value string | ||||||
| 			value, ok = validateCookie(cookie, p.CookieSeed) | 			value, ok = validateCookie(cookie, p.CookieSeed) | ||||||
| 			components := strings.Split(value, "|") | 			if ok { | ||||||
| 			email = components[0] | 				email, user, access_token, err = parseCookieValue( | ||||||
| 			if len(components) == 2 { | 					value, p.AesCipher) | ||||||
| 				access_token, err = decodeAccessToken(p.AesCipher, components[1]) |  | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					log.Printf("error decoding access token: %s", err) | 					log.Printf(err.Error()) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			user = strings.Split(email, "@")[0] |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue