auth
auth/oauth2.go
Enable CSRF protection, add expiration to sessions. Sessions gain a CSRF token, which is passed as a parameter to the login page. The login page now checks for that CSRF token, and logs a CSRF attempt if the token does not match. I also added an expiration to sessions, so they don't last forever. Sessions should be pretty short--we just need to stay logged in for long enough to approve the OAuth request. Everything after that should be cookie based. Finally, I added a configuration parameter to control whether the session cookie should be set to Secure, requiring the use of HTTPS. For production use, this flag is a requirement, but it makes testing extremely difficult, so we need a way to disable it.
1.1 --- a/oauth2.go Sat Jan 24 10:34:33 2015 -0500 1.2 +++ b/oauth2.go Wed Jan 28 07:27:32 2015 -0500 1.3 @@ -16,7 +16,6 @@ 1.4 ) 1.5 1.6 const ( 1.7 - authCookieName = "auth" 1.8 defaultAuthorizationCodeExpiration = 600 // default to ten minute grant expirations 1.9 getAuthorizationCodeTemplateName = "get_grant" 1.10 ) 1.11 @@ -277,7 +276,14 @@ 1.12 return 1.13 } 1.14 if r.Method == "POST" { 1.15 - // BUG(paddy): We need to implement CSRF protection when obtaining a grant code. 1.16 + if checkCSRF(r, session) != nil { 1.17 + log.Println("CSRF attempt detected.") 1.18 + w.WriteHeader(http.StatusInternalServerError) 1.19 + context.Render(w, getAuthorizationCodeTemplateName, map[string]interface{}{ 1.20 + "error": template.HTML("There was an error authenticating your request."), 1.21 + }) 1.22 + return 1.23 + } 1.24 if r.PostFormValue("grant") == "approved" { 1.25 var fragment bool 1.26 switch responseType { 1.27 @@ -352,6 +358,7 @@ 1.28 "redirectURL": redirectURL, 1.29 "scope": scope, 1.30 "profile": profile, 1.31 + "csrftoken": session.CSRFToken, 1.32 }) 1.33 } 1.34