fix(auth): recover refresh rotations and configure session lifetime
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestRefreshLostResponseRecovery(t *testing.T) {
|
||||
a, req := authFixture(t)
|
||||
w := req("POST", "/api/login", `{"username":"alice","password":"password-123"}`, "", nil)
|
||||
old := w.Result().Cookies()
|
||||
csrf, sid := cookieValue(old, "dsh_csrf"), cookieValue(old, "dsh_session")
|
||||
w = req("POST", "/api/refresh", "", csrf, old)
|
||||
if w.Code != 200 {
|
||||
t.Fatal(w.Code)
|
||||
}
|
||||
successor := cookieValue(w.Result().Cookies(), "dsh_refresh")
|
||||
// Lose the response, expire access and restart the server: recovery is durable
|
||||
// and does not depend on an active access cookie or a short grace timer.
|
||||
for _, c := range old {
|
||||
if c.Name == "dsh_access" {
|
||||
c.Value = a.accessJWT(sid, "alice", time.Now().Add(-time.Hour))
|
||||
}
|
||||
}
|
||||
b := New(a.s, a.root)
|
||||
b.origin = a.origin
|
||||
r := httptest.NewRequest("POST", "/api/refresh", strings.NewReader(""))
|
||||
r.Header.Set("Origin", a.origin)
|
||||
r.Header.Set("X-CSRF-Token", csrf)
|
||||
for _, c := range old {
|
||||
r.AddCookie(c)
|
||||
}
|
||||
w = httptest.NewRecorder()
|
||||
b.Handler().ServeHTTP(w, r)
|
||||
if w.Code != 200 || cookieValue(w.Result().Cookies(), "dsh_refresh") != successor {
|
||||
t.Fatal("lost response recovery failed", w.Code)
|
||||
}
|
||||
current := w.Result().Cookies()
|
||||
w = req("POST", "/api/refresh", "", csrf, current)
|
||||
if w.Code != 200 {
|
||||
t.Fatal(w.Code)
|
||||
}
|
||||
if w = req("POST", "/api/refresh", "", csrf, old); w.Code != 401 || len(w.Result().Cookies()) != 0 {
|
||||
t.Fatal("two-generation-old token accepted", w.Code)
|
||||
}
|
||||
bad := []*http.Cookie{{Name: "dsh_session", Value: sid}, {Name: "dsh_refresh", Value: "invalid"}}
|
||||
if w = req("POST", "/api/refresh", "", csrf, bad); w.Code != 401 {
|
||||
t.Fatal(w.Code)
|
||||
}
|
||||
if _, err := a.s.DB.Exec("UPDATE sessions SET expires=? WHERE id=?", time.Now().Unix(), sid); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if w = req("POST", "/api/refresh", "", csrf, current); w.Code == 200 || len(w.Result().Cookies()) != 0 {
|
||||
t.Fatal("expired session recovered")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user