session_test.go 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package appproxy
  2. import (
  3. "testing"
  4. "time"
  5. )
  6. func TestTicketLifecycle(t *testing.T) {
  7. s := newSessionStore()
  8. lookup := func(u string) *Identity { return testUsers[u] }
  9. tk := s.issueTicket("alice", "app", "/page")
  10. if _, _, ok := s.claimTicket(tk, "other"); ok {
  11. t.Fatalf("a ticket must not open another app")
  12. }
  13. if _, _, ok := s.claimTicket(tk, "app"); ok {
  14. t.Fatalf("a failed claim must still consume the ticket")
  15. }
  16. tk = s.issueTicket("alice", "app", "/page")
  17. token, returnTo, ok := s.claimTicket(tk, "app")
  18. if !ok || returnTo != "/page" {
  19. t.Fatalf("claim = %v %q", ok, returnTo)
  20. }
  21. if id := s.resolve(token, "app", lookup); id == nil || id.Username != "alice" {
  22. t.Errorf("resolve = %+v", id)
  23. }
  24. if id := s.resolve(token, "other", lookup); id != nil {
  25. t.Errorf("a session must not open another app")
  26. }
  27. if id := s.resolve("", "app", lookup); id != nil {
  28. t.Errorf("empty token resolved")
  29. }
  30. }
  31. func TestExpiredTicket(t *testing.T) {
  32. s := newSessionStore()
  33. tk := s.issueTicket("alice", "app", "/")
  34. s.tickets[tk].expires = time.Now().Add(-time.Second)
  35. if _, _, ok := s.claimTicket(tk, "app"); ok {
  36. t.Errorf("expired ticket accepted")
  37. }
  38. }
  39. func TestSessionRevalidation(t *testing.T) {
  40. s := newSessionStore()
  41. users := map[string]*Identity{"carol": {Username: "carol"}}
  42. lookup := func(u string) *Identity { return users[u] }
  43. tk := s.issueTicket("carol", "app", "/")
  44. token, _, _ := s.claimTicket(tk, "app")
  45. if s.resolve(token, "app", lookup) == nil {
  46. t.Fatalf("session not resolved")
  47. }
  48. //The account is removed; once the cached record is stale the session ends
  49. delete(users, "carol")
  50. s.sessions[token].checkedAt = time.Now().Add(-2 * identityRecheck)
  51. if s.resolve(token, "app", lookup) != nil {
  52. t.Errorf("session of a removed user still valid")
  53. }
  54. if _, ok := s.sessions[token]; ok {
  55. t.Errorf("session of a removed user not dropped")
  56. }
  57. }
  58. func TestDropEndpointSessions(t *testing.T) {
  59. s := newSessionStore()
  60. lookup := func(u string) *Identity { return testUsers[u] }
  61. a, _, _ := s.claimTicket(s.issueTicket("alice", "a", "/"), "a")
  62. b, _, _ := s.claimTicket(s.issueTicket("alice", "b", "/"), "b")
  63. s.dropEndpoint("a")
  64. if s.resolve(a, "a", lookup) != nil {
  65. t.Errorf("dropped endpoint session still valid")
  66. }
  67. if s.resolve(b, "b", lookup) == nil {
  68. t.Errorf("other endpoint session dropped")
  69. }
  70. }
  71. func TestSafeReturnPath(t *testing.T) {
  72. tests := map[string]string{
  73. "/page?x=1": "/page?x=1",
  74. "//evil.com": "/",
  75. "https://evil.com": "/",
  76. "/\\evil.com": "/",
  77. "": "/",
  78. }
  79. for in, want := range tests {
  80. if got := safeReturnPath(in); got != want {
  81. t.Errorf("safeReturnPath(%q) = %q, want %q", in, got, want)
  82. }
  83. }
  84. }