From ca2a93ed9f5efd3f874a13332cdf22946d4d14b7 Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Sat, 9 Aug 2014 19:06:37 -0700 Subject: [PATCH] ability to set xsrf token --- server/session/session.go | 20 +++++++++++++++++++- shared/httputil/httputil.go | 25 +++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/server/session/session.go b/server/session/session.go index be3035ec6..c48324ae4 100644 --- a/server/session/session.go +++ b/server/session/session.go @@ -4,6 +4,7 @@ import ( "net/http" "github.com/drone/drone/server/database" + "github.com/drone/drone/shared/httputil" "github.com/drone/drone/shared/model" "github.com/gorilla/securecookie" "github.com/gorilla/sessions" @@ -13,6 +14,9 @@ import ( var cookies = sessions.NewCookieStore( securecookie.GenerateRandomKey(64)) +// stores sessions using secure cookies. +var xsrftoken = string(securecookie.GenerateRandomKey(32)) + type Session interface { User(r *http.Request) *model.User UserToken(r *http.Request) *model.User @@ -31,7 +35,7 @@ func NewSession(users database.UserManager) Session { } } -// User gets the currently authenticated user from the secure cookie session. +// User gets the currently authenticated user. func (s *session) User(r *http.Request) *model.User { switch { case r.FormValue("access_token") == "": @@ -42,6 +46,19 @@ func (s *session) User(r *http.Request) *model.User { return nil } +// UserXsrf gets the currently authenticated user and +// validates the xsrf session token, if necessary. +func (s *session) UserXsrf(r *http.Request) *model.User { + user := s.User(r) + if user == nil || r.FormValue("access_token") != "" { + return user + } + if !httputil.CheckXsrf(r, xsrftoken, user.Login) { + return nil + } + return user +} + // UserToken gets the currently authenticated user for the given auth token. func (s *session) UserToken(r *http.Request) *model.User { token := r.FormValue("access_token") @@ -70,6 +87,7 @@ func (s *session) SetUser(w http.ResponseWriter, r *http.Request, u *model.User) sess, _ := cookies.Get(r, "_sess") sess.Values["uid"] = u.ID sess.Save(r, w) + httputil.SetXsrf(w, r, xsrftoken, u.Login) } // Clear removes the user from the session. diff --git a/shared/httputil/httputil.go b/shared/httputil/httputil.go index a71dc73d9..395bca3ee 100644 --- a/shared/httputil/httputil.go +++ b/shared/httputil/httputil.go @@ -3,6 +3,8 @@ package httputil import ( "net/http" "strings" + + "code.google.com/p/xsrftoken" ) // IsHttps is a helper function that evaluates the http.Request @@ -103,3 +105,26 @@ func DelCookie(w http.ResponseWriter, r *http.Request, name string) { http.SetCookie(w, &cookie) } + +// SetXsrf writes the cookie value. +func SetXsrf(w http.ResponseWriter, r *http.Request, token, login string) { + cookie := http.Cookie{ + Name: "XSRF-TOKEN", + Value: xsrftoken.Generate(token, login, "/"), + Path: "/", + Domain: r.URL.Host, + HttpOnly: false, + Secure: IsHttps(r), + } + + http.SetCookie(w, &cookie) +} + +// CheckXsrf verifies the xsrf value. +func CheckXsrf(r *http.Request, token, login string) bool { + if r.Method == "GET" { + return true + } + return xsrftoken.Valid( + r.Header.Get("X-XSRF-TOKEN"), token, login, "/") +}