add XSRF cookie #16

This commit is contained in:
Umputun
2018-05-13 12:27:03 -05:00
parent 5cbdc6f0f6
commit 214199e10f
3 changed files with 53 additions and 1 deletions
+25
View File
@@ -3,6 +3,7 @@ package auth
import (
"encoding/base64"
"log"
"net/http"
"strings"
@@ -59,6 +60,30 @@ func (a *Authenticator) Auth(reqAuth bool) func(http.Handler) http.Handler {
return
}
xsrfStatus := func() bool {
xsrfToken := r.Header.Get("X-XSRF-TOKEN")
sessionToken, headerOk := session.Values["xsrf_token"]
if (xsrfToken == "" || sessionToken == nil || !headerOk) && reqAuth {
log.Print("[WARN] no xsrf_token in session")
return false
}
if xsrfToken != sessionToken {
log.Printf("[WARN] xsrf header not matched session token, %q != %q", xsrfToken, sessionToken)
return false
}
return true
}()
if xsrfStatus {
if reqAuth {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
h.ServeHTTP(w, r) // in anonymous mode just pass it to next handler
return
}
if ok { // if uinfo in session, populate to context
user := uinfoData.(store.User)
for _, admin := range a.Admins {
+26 -1
View File
@@ -10,6 +10,7 @@ import (
"io/ioutil"
"log"
"net/http"
"time"
"github.com/go-chi/chi"
"github.com/go-chi/render"
@@ -173,10 +174,19 @@ func (p Provider) authHandler(w http.ResponseWriter, r *http.Request) {
}
session.Values["uinfo"] = u
xsrfToken := p.randToken()
session.Values["xsrf_token"] = xsrfToken
xsrfCookie := http.Cookie{Name: "XSRF-TOKEN", Value: p.randToken(), HttpOnly: false, Path: "/",
MaxAge: 3600 * 24 * 365, Secure: true,
}
http.SetCookie(w, &xsrfCookie)
if err = session.Save(r, w); err != nil {
rest.SendErrorJSON(w, r, http.StatusInternalServerError, err, "failed to save user info")
return
}
p.sendXsrfCookie(w)
log.Printf("[DEBUG] user info %+v", session.Values["uinfo"])
@@ -185,7 +195,6 @@ func (p Provider) authHandler(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, fromURL.(string), http.StatusTemporaryRedirect)
return
}
render.JSON(w, r, jData)
}
@@ -201,6 +210,10 @@ func (p Provider) LogoutHandler(w http.ResponseWriter, r *http.Request) {
delete(session.Values, "uinfo")
delete(session.Values, "from")
delete(session.Values, "state")
delete(session.Values, "xsrf_token")
xsrfCookie := http.Cookie{Name: "XSRF-TOKEN", Value: "", HttpOnly: false, Path: "/",
MaxAge: -1, Expires: time.Unix(0, 0), Secure: true}
http.SetCookie(w, &xsrfCookie)
if err = session.Save(r, w); err != nil {
rest.SendErrorJSON(w, r, http.StatusInternalServerError, err, "failed to reset user info")
@@ -209,6 +222,18 @@ func (p Provider) LogoutHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("[DEBUG] logout, %+v", session.Values)
}
func (p Provider) sendXsrfCookie(w http.ResponseWriter) {
xsrfCookie := http.Cookie{
Name: "XSRF-TOKEN",
Value: p.randToken(),
HttpOnly: false,
Path: "/",
MaxAge: 3600 * 24 * 365,
Secure: true,
}
http.SetCookie(w, &xsrfCookie)
}
func (p Provider) randToken() string {
b := make([]byte, 32)
if _, err := rand.Read(b); err != nil {
+2
View File
@@ -32,6 +32,7 @@ func TestLogin(t *testing.T) {
body, err := ioutil.ReadAll(resp.Body)
assert.Nil(t, err)
t.Logf("resp %s", string(body))
t.Logf("headers: %+v", resp.Header)
u := store.User{}
err = json.Unmarshal(body, &u)
assert.Nil(t, err)
@@ -58,6 +59,7 @@ func TestLogout(t *testing.T) {
s, err := sessionStore.Get(nil, "remark")
assert.Nil(t, err)
t.Log(s.Values)
assert.Equal(t, 0, len(s.Values))
}