add XSRF cookie #16
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user