Implement Phase 2: password auth (Argon2id + bearer tokens)
- Argon2id password hashing and verification with configurable params - Bearer token generation (32-byte random), SHA-256 hashed storage, TTL-based expiry - User creation and authentication helpers - auth_tokens table added to migrations - 6 tests: hash/verify, wrong password, create/auth user, token create/validate, token expiry Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
128
internal/auth/auth_test.go
Normal file
128
internal/auth/auth_test.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.wntrmute.dev/kyle/eng-pad-server/internal/db"
|
||||
)
|
||||
|
||||
func setupTestDB(t *testing.T) *db.TestDB {
|
||||
t.Helper()
|
||||
dir := t.TempDir()
|
||||
database, err := db.Open(filepath.Join(dir, "test.db"))
|
||||
if err != nil {
|
||||
t.Fatalf("open: %v", err)
|
||||
}
|
||||
if err := db.Migrate(database); err != nil {
|
||||
t.Fatalf("migrate: %v", err)
|
||||
}
|
||||
t.Cleanup(func() { _ = database.Close() })
|
||||
return &db.TestDB{DB: database}
|
||||
}
|
||||
|
||||
func TestHashAndVerify(t *testing.T) {
|
||||
hash, err := HashPassword("testpassword", DefaultParams)
|
||||
if err != nil {
|
||||
t.Fatalf("hash: %v", err)
|
||||
}
|
||||
|
||||
ok, err := VerifyPassword("testpassword", hash)
|
||||
if err != nil {
|
||||
t.Fatalf("verify: %v", err)
|
||||
}
|
||||
if !ok {
|
||||
t.Fatal("expected password to verify")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyWrongPassword(t *testing.T) {
|
||||
hash, err := HashPassword("correct", DefaultParams)
|
||||
if err != nil {
|
||||
t.Fatalf("hash: %v", err)
|
||||
}
|
||||
|
||||
ok, err := VerifyPassword("wrong", hash)
|
||||
if err != nil {
|
||||
t.Fatalf("verify: %v", err)
|
||||
}
|
||||
if ok {
|
||||
t.Fatal("expected password to not verify")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateAndAuthenticateUser(t *testing.T) {
|
||||
tdb := setupTestDB(t)
|
||||
|
||||
id, err := CreateUser(tdb.DB, "alice", "hunter2", DefaultParams)
|
||||
if err != nil {
|
||||
t.Fatalf("create user: %v", err)
|
||||
}
|
||||
if id <= 0 {
|
||||
t.Fatalf("expected positive ID, got %d", id)
|
||||
}
|
||||
|
||||
authID, err := AuthenticateUser(tdb.DB, "alice", "hunter2")
|
||||
if err != nil {
|
||||
t.Fatalf("auth: %v", err)
|
||||
}
|
||||
if authID != id {
|
||||
t.Fatalf("expected user ID %d, got %d", id, authID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthenticateWrongPassword(t *testing.T) {
|
||||
tdb := setupTestDB(t)
|
||||
|
||||
_, err := CreateUser(tdb.DB, "alice", "hunter2", DefaultParams)
|
||||
if err != nil {
|
||||
t.Fatalf("create: %v", err)
|
||||
}
|
||||
|
||||
_, err = AuthenticateUser(tdb.DB, "alice", "wrong")
|
||||
if err == nil {
|
||||
t.Fatal("expected error for wrong password")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTokenCreateAndValidate(t *testing.T) {
|
||||
tdb := setupTestDB(t)
|
||||
|
||||
userID, err := CreateUser(tdb.DB, "alice", "pass", DefaultParams)
|
||||
if err != nil {
|
||||
t.Fatalf("create user: %v", err)
|
||||
}
|
||||
|
||||
token, err := CreateToken(tdb.DB, userID, time.Hour)
|
||||
if err != nil {
|
||||
t.Fatalf("create token: %v", err)
|
||||
}
|
||||
|
||||
gotID, err := ValidateToken(tdb.DB, token)
|
||||
if err != nil {
|
||||
t.Fatalf("validate: %v", err)
|
||||
}
|
||||
if gotID != userID {
|
||||
t.Fatalf("expected user %d, got %d", userID, gotID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTokenExpired(t *testing.T) {
|
||||
tdb := setupTestDB(t)
|
||||
|
||||
userID, err := CreateUser(tdb.DB, "alice", "pass", DefaultParams)
|
||||
if err != nil {
|
||||
t.Fatalf("create user: %v", err)
|
||||
}
|
||||
|
||||
token, err := CreateToken(tdb.DB, userID, -time.Hour) // Already expired
|
||||
if err != nil {
|
||||
t.Fatalf("create token: %v", err)
|
||||
}
|
||||
|
||||
_, err = ValidateToken(tdb.DB, token)
|
||||
if err == nil {
|
||||
t.Fatal("expected error for expired token")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user