Files
chat/internal/db/auth_test.go
user cd9fd0c5c5
All checks were successful
check / check (push) Successful in 2m21s
refactor: replace Bearer token auth with HttpOnly cookies
- Remove POST /api/v1/register endpoint entirely
- Session creation (POST /api/v1/session) now sets neoirc_auth HttpOnly
  cookie instead of returning token in JSON body
- Login (POST /api/v1/login) now sets neoirc_auth HttpOnly cookie
  instead of returning token in JSON body
- Add PASS IRC command for setting session password (enables multi-client
  login via POST /api/v1/login)
- All per-request auth reads from neoirc_auth cookie instead of
  Authorization: Bearer header
- Cookie properties: HttpOnly, SameSite=Strict, Secure when behind TLS
- Logout and QUIT clear the auth cookie
- Update CORS to AllowCredentials:true with origin reflection
- Remove Authorization from CORS AllowedHeaders
- Update CLI client to use cookie jar (net/http/cookiejar)
- Remove Token field from SessionResponse
- Add SetPassword to DB layer, remove RegisterUser
- Comprehensive test updates for cookie-based auth
- Add tests: TestPassCommand, TestPassCommandShortPassword,
  TestPassCommandEmpty, TestSessionCookie
- Update README extensively: auth model, API reference, curl examples,
  security model, design principles, roadmap

closes #83
2026-03-17 20:33:12 -07:00

157 lines
2.7 KiB
Go

package db_test
import (
"testing"
_ "modernc.org/sqlite"
)
func TestSetPassword(t *testing.T) {
t.Parallel()
database := setupTestDB(t)
ctx := t.Context()
sessionID, _, _, err :=
database.CreateSession(ctx, "passuser")
if err != nil {
t.Fatal(err)
}
err = database.SetPassword(
ctx, sessionID, "password123",
)
if err != nil {
t.Fatal(err)
}
// Verify we can now log in with the password.
loginSID, loginCID, loginToken, err :=
database.LoginUser(ctx, "passuser", "password123")
if err != nil {
t.Fatal(err)
}
if loginSID == 0 || loginCID == 0 || loginToken == "" {
t.Fatal("expected valid ids and token")
}
}
func TestSetPasswordThenWrongLogin(t *testing.T) {
t.Parallel()
database := setupTestDB(t)
ctx := t.Context()
sessionID, _, _, err :=
database.CreateSession(ctx, "wrongpw")
if err != nil {
t.Fatal(err)
}
err = database.SetPassword(
ctx, sessionID, "correctpass",
)
if err != nil {
t.Fatal(err)
}
loginSID, loginCID, loginToken, loginErr :=
database.LoginUser(ctx, "wrongpw", "wrongpass12")
if loginErr == nil {
t.Fatal("expected error for wrong password")
}
_ = loginSID
_ = loginCID
_ = loginToken
}
func TestLoginUser(t *testing.T) {
t.Parallel()
database := setupTestDB(t)
ctx := t.Context()
sessionID, _, _, err :=
database.CreateSession(ctx, "loginuser")
if err != nil {
t.Fatal(err)
}
err = database.SetPassword(
ctx, sessionID, "mypassword",
)
if err != nil {
t.Fatal(err)
}
loginSID, loginCID, token, err :=
database.LoginUser(ctx, "loginuser", "mypassword")
if err != nil {
t.Fatal(err)
}
if loginSID == 0 || loginCID == 0 || token == "" {
t.Fatal("expected valid ids and token")
}
// Verify the new token works.
_, _, nick, err :=
database.GetSessionByToken(ctx, token)
if err != nil {
t.Fatal(err)
}
if nick != "loginuser" {
t.Fatalf("expected loginuser, got %s", nick)
}
}
func TestLoginUserNoPassword(t *testing.T) {
t.Parallel()
database := setupTestDB(t)
ctx := t.Context()
// Create anonymous session (no password).
anonSID, anonCID, anonToken, err :=
database.CreateSession(ctx, "anon")
if err != nil {
t.Fatal(err)
}
_ = anonSID
_ = anonCID
_ = anonToken
loginSID, loginCID, loginToken, loginErr :=
database.LoginUser(ctx, "anon", "anything1")
if loginErr == nil {
t.Fatal(
"expected error for login on passwordless account",
)
}
_ = loginSID
_ = loginCID
_ = loginToken
}
func TestLoginUserNonexistent(t *testing.T) {
t.Parallel()
database := setupTestDB(t)
ctx := t.Context()
loginSID, loginCID, loginToken, err :=
database.LoginUser(ctx, "ghost", "password123")
if err == nil {
t.Fatal("expected error for nonexistent user")
}
_ = loginSID
_ = loginCID
_ = loginToken
}