package session import ( "errors" "testing" "time" ) func TestIssueAndVerify(t *testing.T) { s := NewSigner([]byte("0123456789abcdef0123456789abcdef"), nil, time.Hour) raw, tok, err := s.IssueWithRole("admin@example.com", "admin") if err != nil { t.Fatalf("issue: %v", err) } if tok.Actor != "admin@example.com" || tok.Role != "admin" { t.Fatalf("token claims: %+v", tok) } got, err := s.Verify(raw) if err != nil { t.Fatalf("verify: %v", err) } if got.Actor != tok.Actor || got.Role != tok.Role { t.Fatalf("roundtrip mismatch: %+v vs %+v", got, tok) } } func TestVerifyRejectsTampered(t *testing.T) { s := NewSigner([]byte("0123456789abcdef0123456789abcdef"), nil, time.Hour) raw, _, _ := s.Issue("a") tampered := raw[:len(raw)-2] + "AA" if _, err := s.Verify(tampered); !errors.Is(err, ErrInvalidToken) { t.Fatalf("expected ErrInvalidToken, got %v", err) } } func TestVerifyExpired(t *testing.T) { now := time.Unix(1_000_000, 0).UTC() s := NewSigner([]byte("0123456789abcdef0123456789abcdef"), func() time.Time { return now }, time.Minute) raw, _, _ := s.Issue("a") // shift clock forward past Exp s.Now = func() time.Time { return now.Add(2 * time.Minute) } if _, err := s.Verify(raw); !errors.Is(err, ErrExpiredToken) { t.Fatalf("expected ErrExpiredToken, got %v", err) } } func TestVerifyEmptyRaw(t *testing.T) { s := NewSigner([]byte("0123456789abcdef0123456789abcdef"), nil, time.Hour) if _, err := s.Verify(""); !errors.Is(err, ErrInvalidToken) { t.Fatalf("expected ErrInvalidToken, got %v", err) } }