69 lines
2.3 KiB
Go
69 lines
2.3 KiB
Go
package session
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestSessionRotationCookieAndCSRF(t *testing.T) {
|
|
manager, err := New([]byte(strings.Repeat("k", 32)), time.Hour, true)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
request := httptest.NewRequest(http.MethodGet, "https://chorus.test/api/session", nil)
|
|
response := httptest.NewRecorder()
|
|
anonymous, err := manager.Ensure(response, request)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
cookie := response.Result().Cookies()[0]
|
|
if !cookie.HttpOnly || !cookie.Secure || cookie.SameSite != http.SameSiteLaxMode || anonymous.UserID != 0 {
|
|
t.Fatalf("cookie/state = %#v %#v", cookie, anonymous)
|
|
}
|
|
request.AddCookie(cookie)
|
|
loginResponse := httptest.NewRecorder()
|
|
authenticated, err := manager.Authenticate(loginResponse, request, 42)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if authenticated.ID == anonymous.ID || authenticated.CSRFToken == anonymous.CSRFToken {
|
|
t.Fatal("login did not rotate session and CSRF")
|
|
}
|
|
if _, ok := manager.Get(request); ok {
|
|
t.Fatal("old session remained valid")
|
|
}
|
|
newCookie := loginResponse.Result().Cookies()[0]
|
|
csrfRequest := httptest.NewRequest(http.MethodPost, "https://chorus.test/api", nil)
|
|
csrfRequest.AddCookie(newCookie)
|
|
csrfRequest.Header.Set("X-CSRF-Token", authenticated.CSRFToken)
|
|
if state, ok := manager.Get(csrfRequest); !ok || !manager.ValidateCSRF(csrfRequest, state) {
|
|
t.Fatal("new session CSRF was rejected")
|
|
}
|
|
csrfRequest.Header.Set("X-CSRF-Token", "tampered")
|
|
if manager.ValidateCSRF(csrfRequest, authenticated) {
|
|
t.Fatal("tampered CSRF was accepted")
|
|
}
|
|
}
|
|
func TestTamperedAndExpiredCookie(t *testing.T) {
|
|
manager, _ := New([]byte(strings.Repeat("k", 32)), time.Millisecond, false)
|
|
response := httptest.NewRecorder()
|
|
state, _ := manager.Ensure(response, httptest.NewRequest(http.MethodGet, "http://test/", nil))
|
|
cookie := response.Result().Cookies()[0]
|
|
cookie.Value += "x"
|
|
request := httptest.NewRequest(http.MethodGet, "http://test/", nil)
|
|
request.AddCookie(cookie)
|
|
if _, ok := manager.Get(request); ok {
|
|
t.Fatal("tampered cookie accepted")
|
|
}
|
|
manager.now = func() time.Time { return state.ExpiresAt.Add(time.Second) }
|
|
validCookie := response.Result().Cookies()[0]
|
|
request = httptest.NewRequest(http.MethodGet, "http://test/", nil)
|
|
request.AddCookie(validCookie)
|
|
if _, ok := manager.Get(request); ok {
|
|
t.Fatal("expired session accepted")
|
|
}
|
|
}
|