package platform import ( "net/http" "net/http/httptest" "strings" "testing" ) const htmlDoc = "cdrop" func htmlHandler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "text/html; charset=utf-8") w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(htmlDoc)) }) } func TestSessionInjectIntoDocument(t *testing.T) { session := &LoginResult{ AccessToken: "acc-token", RefreshToken: "ref-token", User: UserInfo{ID: "u-1", Name: "alice"}, } h := SessionInjectMiddleware(session, "my-host", "", "macos")(htmlHandler()) rec := httptest.NewRecorder() h.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/", nil)) body := rec.Body.String() if !strings.Contains(body, "window.__CDROP_BOOT__") { t.Fatalf("boot global not injected:\n%s", body) } if !strings.Contains(body, `"access_token":"acc-token"`) { t.Errorf("access token not in injected payload:\n%s", body) } // Credential policy: the refresh_token must NEVER reach the page. if strings.Contains(body, "ref-token") || strings.Contains(body, "refresh_token") { t.Errorf("refresh_token must not be injected into the page:\n%s", body) } if !strings.Contains(body, `"device_name":"my-host"`) { t.Errorf("device name not in injected payload:\n%s", body) } if !strings.Contains(body, `"device_type":"macos"`) { t.Errorf("device type not in injected payload:\n%s", body) } // Injected before so it runs before the deferred module bundle. if strings.Index(body, "__CDROP_BOOT__") > strings.Index(body, "") { t.Error("injection must precede ") } } func TestSessionInjectPassesThroughNonDocument(t *testing.T) { apiBody := "streamed-api-body" next := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { _, _ = w.Write([]byte(apiBody)) }) h := SessionInjectMiddleware(&LoginResult{AccessToken: "x"}, "h", "", "")(next) rec := httptest.NewRecorder() h.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/api/hub/events", nil)) if rec.Body.String() != apiBody { t.Errorf("non-document request must pass through unchanged, got %q", rec.Body.String()) } } func TestSessionInjectNilSessionStillInjectsDeviceBoot(t *testing.T) { // Logged out, the boot state is still injected — the page needs the device // name / api_base / device_type before login — but with a null session, and // no token of any kind leaks. h := SessionInjectMiddleware(nil, "my-host", "http://127.0.0.1:5000", "windows")(htmlHandler()) rec := httptest.NewRecorder() h.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/", nil)) body := rec.Body.String() if !strings.Contains(body, "window.__CDROP_BOOT__") { t.Fatalf("boot global must be injected even when logged out:\n%s", body) } if !strings.Contains(body, `"session":null`) { t.Errorf("logged-out boot must carry a null session:\n%s", body) } if !strings.Contains(body, `"device_name":"my-host"`) || !strings.Contains(body, `"device_type":"windows"`) || !strings.Contains(body, `"api_base":"http://127.0.0.1:5000"`) { t.Errorf("device boot fields not injected:\n%s", body) } if strings.Contains(body, "access_token") { t.Errorf("no token must appear when logged out:\n%s", body) } } func TestSessionInjectEscapesScriptBreakout(t *testing.T) { // A display name containing must not break out of the inline tag. session := &LoginResult{AccessToken: "acc", User: UserInfo{Name: "x"}} h := SessionInjectMiddleware(session, "h", "", "")(htmlHandler()) rec := httptest.NewRecorder() h.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/", nil)) body := rec.Body.String() // The literal closing tag from the name must NOT appear verbatim; encoding/json // HTML-escapes < / > to < / > by default. if strings.Contains(body, "x") { t.Errorf("script breakout not escaped:\n%s", body) } if !strings.Contains(body, ``) { t.Errorf("expected HTML-escaped name in payload:\n%s", body) } }