package auth import ( "context" "errors" "testing" "golang.org/x/crypto/bcrypt" "kereru.forms/internal/config" ) func TestLocalPasswordLoginAndAuthenticate(t *testing.T) { cfg := config.Default().Auth cfg.LocalPassword = "secret" cfg.LocalTokenSecret = "test-secret" service, err := New(context.Background(), cfg) if err != nil { t.Fatalf("new auth service: %v", err) } token, user, err := service.Login("secret") if err != nil { t.Fatalf("login: %v", err) } if token == "" { t.Fatal("expected a token") } if !user.CanAdmin || !user.CanView { t.Fatalf("expected admin and view roles, got %+v", user) } authenticated, err := service.Authenticate(context.Background(), token) if err != nil { t.Fatalf("authenticate: %v", err) } if authenticated.ID != "local" || !authenticated.CanAdmin || !authenticated.CanView { t.Fatalf("unexpected authenticated user: %+v", authenticated) } if _, _, err := service.Login("wrong"); !errors.Is(err, ErrInvalidCredentials) { t.Fatalf("expected invalid credentials, got %v", err) } if _, err := service.Authenticate(context.Background(), token+"x"); !errors.Is(err, ErrInvalidToken) { t.Fatalf("expected invalid token, got %v", err) } } func TestLocalPasswordSupportsBcrypt(t *testing.T) { hash, err := bcrypt.GenerateFromPassword([]byte("hashed-secret"), bcrypt.MinCost) if err != nil { t.Fatalf("hash password: %v", err) } cfg := config.Default().Auth cfg.LocalPassword = string(hash) cfg.LocalTokenSecret = "test-secret" service, err := New(context.Background(), cfg) if err != nil { t.Fatalf("new auth service: %v", err) } if _, _, err := service.Login("hashed-secret"); err != nil { t.Fatalf("login with bcrypt password: %v", err) } } func TestClaimValuesSupportsNestedPathsAndArrays(t *testing.T) { claims := map[string]any{ "roles": []any{"admin", "view", "admin"}, "realm_access": map[string]any{ "roles": []any{"viewer", "auditor"}, }, } if got := claimValues(claims, "roles"); len(got) != 2 || got[0] != "admin" || got[1] != "view" { t.Fatalf("unexpected flat roles: %#v", got) } if got := claimValues(claims, "realm_access.roles"); len(got) != 2 || got[0] != "viewer" || got[1] != "auditor" { t.Fatalf("unexpected nested roles: %#v", got) } if got := claimValues(claims, "missing.roles"); got != nil { t.Fatalf("expected nil for missing path, got %#v", got) } }