login_psp_test.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package handlers
  2. import (
  3. "context"
  4. "log/slog"
  5. "net/http"
  6. "net/http/httptest"
  7. "net/url"
  8. "strings"
  9. "testing"
  10. "github.com/stretchr/testify/assert"
  11. "github.com/mk6i/open-oscar-server/wire"
  12. )
  13. func TestAuthHandler_LoginPSP_GET(t *testing.T) {
  14. handler := &AuthHandler{Logger: slog.Default()}
  15. req := httptest.NewRequest(http.MethodGet, "/_cqr/login/login.psp?devId=dev1&succUrl=http%3A%2F%2Flocalhost%3A8000%2F", nil)
  16. rr := httptest.NewRecorder()
  17. handler.LoginPSP(rr, req)
  18. assert.Equal(t, http.StatusOK, rr.Code)
  19. assert.Contains(t, rr.Header().Get("Content-Type"), "text/html")
  20. assert.Contains(t, rr.Body.String(), "AIM Sign In")
  21. assert.Contains(t, rr.Body.String(), `name="devId" value="dev1"`)
  22. }
  23. func TestAuthHandler_Logout(t *testing.T) {
  24. handler := &AuthHandler{Logger: slog.Default()}
  25. req := httptest.NewRequest(http.MethodGet, "/auth/logout?f=json&a=sometoken&devId=dev1&succUrl=http%3A%2F%2Flocalhost%3A8000%2F.client%2F", nil)
  26. rr := httptest.NewRecorder()
  27. handler.Logout(rr, req)
  28. assert.Equal(t, http.StatusFound, rr.Code)
  29. loc, err := url.Parse(rr.Header().Get("Location"))
  30. assert.NoError(t, err)
  31. assert.Equal(t, "/_cqr/login/login.psp", loc.Path)
  32. assert.Equal(t, "dev1", loc.Query().Get("devId"))
  33. assert.Equal(t, "http://localhost:8000/.client/", loc.Query().Get("succUrl"))
  34. // SSO cookies are expired so the browser is logged out.
  35. cleared := map[string]bool{}
  36. for _, c := range rr.Result().Cookies() {
  37. if c.MaxAge < 0 {
  38. cleared[c.Name] = true
  39. }
  40. }
  41. for _, name := range []string{"RSP_USER", "RSP_LOCAL", "localAuthUser", "oldAimToken"} {
  42. assert.True(t, cleared[name], "expected %s cookie to be cleared", name)
  43. }
  44. }
  45. func TestAuthHandler_LoginPSP_POST_Success(t *testing.T) {
  46. handler := &AuthHandler{
  47. AuthService: &testAuthService{
  48. flapLogin: func(ctx context.Context, inFrame wire.FLAPSignonFrame, advertisedHost string) (wire.TLVRestBlock, error) {
  49. return successfulLoginBlock(), nil
  50. },
  51. },
  52. Logger: slog.Default(),
  53. }
  54. form := url.Values{}
  55. form.Set("loginId", "testuser")
  56. form.Set("password", "secret")
  57. form.Set("devId", "dev1")
  58. form.Set("succUrl", "http://localhost:8000/")
  59. req := httptest.NewRequest(http.MethodPost, "/_cqr/login/login.psp", strings.NewReader(form.Encode()))
  60. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  61. rr := httptest.NewRecorder()
  62. handler.LoginPSP(rr, req)
  63. assert.Equal(t, http.StatusFound, rr.Code)
  64. assert.Equal(t, "http://localhost:8000/", rr.Header().Get("Location"))
  65. cookies := rr.Result().Cookies()
  66. names := make(map[string]string, len(cookies))
  67. for _, c := range cookies {
  68. names[c.Name] = c.Value
  69. }
  70. assert.Equal(t, "testuser", names["RSP_USER"])
  71. assert.Equal(t, "testuser", names["RSP_LOCAL"])
  72. assert.Equal(t, "testuser||testuser", names["localAuthUser"])
  73. }
  74. func TestAuthHandler_LoginPSP_POST_InvalidCredentials(t *testing.T) {
  75. handler := &AuthHandler{
  76. AuthService: &testAuthService{
  77. flapLogin: func(ctx context.Context, inFrame wire.FLAPSignonFrame, advertisedHost string) (wire.TLVRestBlock, error) {
  78. return failedLoginBlock(), nil
  79. },
  80. },
  81. Logger: slog.Default(),
  82. }
  83. form := url.Values{}
  84. form.Set("loginId", "testuser")
  85. form.Set("password", "wrong")
  86. req := httptest.NewRequest(http.MethodPost, "/_cqr/login/login.psp", strings.NewReader(form.Encode()))
  87. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  88. rr := httptest.NewRecorder()
  89. handler.LoginPSP(rr, req)
  90. assert.Equal(t, http.StatusOK, rr.Code)
  91. assert.Contains(t, rr.Body.String(), "Invalid screen name or password")
  92. }
  93. func TestSafeLoginRedirectURL(t *testing.T) {
  94. req := httptest.NewRequest(http.MethodGet, "http://localhost/_cqr/login/login.psp", nil)
  95. assert.Equal(t, "http://localhost:8000/", safeLoginRedirectURL(req, "http://localhost:8000/"))
  96. assert.Equal(t, "http://localhost/", safeLoginRedirectURL(req, "http://evil.example/"))
  97. }