feat(auth): implement user and device authentication

This commit is contained in:
QiuSW
2026-07-26 15:18:48 +08:00
parent c5d3b215ff
commit 49db5b8305
66 changed files with 6216 additions and 271 deletions
@@ -112,7 +112,7 @@ func TestNewTaskIssuesReusableStrictCSRFCookie(t *testing.T) {
cookie := csrfCookie(t, response)
if !cookie.HttpOnly ||
cookie.SameSite != http.SameSiteStrictMode ||
cookie.Path != "/tasks" {
cookie.Path != "/" {
t.Fatalf("CSRF cookie = %+v", cookie)
}
body := response.Body.String()
@@ -128,6 +128,7 @@ func TestNewTaskIssuesReusableStrictCSRFCookie(t *testing.T) {
`name="quantity"`,
`name="max_budget"`,
`name="image"`,
`action="/logout"`,
"最高总预算",
} {
if !strings.Contains(body, required) {
@@ -141,6 +142,39 @@ func TestNewTaskIssuesReusableStrictCSRFCookie(t *testing.T) {
assertSecurityHeaders(t, response)
}
func TestNewTaskPrefersRootCSRFCookieDuringLegacyPathMigration(
t *testing.T,
) {
router := newTestRouter(t, &fakeService{})
legacy := mustToken(t)
root := mustToken(t)
for root == legacy {
root = mustToken(t)
}
request := httptest.NewRequest(http.MethodGet, "/tasks/new", nil)
request.AddCookie(&http.Cookie{
Name: csrfCookieName,
Value: legacy,
Path: "/tasks",
})
request.AddCookie(&http.Cookie{
Name: csrfCookieName,
Value: root,
Path: "/",
})
response := httptest.NewRecorder()
router.ServeHTTP(response, request)
if response.Code != http.StatusOK ||
!strings.Contains(
response.Body.String(),
`name="csrf_token" value="`+root+`"`,
) {
t.Fatalf("status/body = %d / %s", response.Code, response.Body)
}
}
func TestCreateTaskRejectsCSRFBeforeCallingService(t *testing.T) {
service := &fakeService{}
router := newTestRouter(t, service)
@@ -622,7 +656,9 @@ func csrfCookie(
) *http.Cookie {
t.Helper()
for _, cookie := range response.Result().Cookies() {
if cookie.Name == csrfCookieName {
if cookie.Name == csrfCookieName &&
cookie.Path == "/" &&
cookie.Value != "" {
return cookie
}
}