package integration_test import ( "context" "net/http" "testing" "time" "galaxy/integration/testenv" usermodel "galaxy/model/user" "galaxy/transcoder" ) // TestSessionRevoke_SubsequentRequestsRejected revokes a session via // the internal endpoint backend exposes (gateway uses the same path) // and asserts the gateway rejects subsequent authenticated requests // bound to that session. func TestSessionRevoke_SubsequentRequestsRejected(t *testing.T) { plat := testenv.Bootstrap(t, testenv.BootstrapOptions{}) ctx, cancel := context.WithTimeout(context.Background(), 90*time.Second) defer cancel() sess := testenv.RegisterSession(t, plat, "pilot+revoke@example.com") gw, err := sess.DialAuthenticated(ctx, plat) if err != nil { t.Fatalf("dial: %v", err) } defer gw.Close() // Sanity: the authenticated path works before revoke. payload, err := transcoder.GetMyAccountRequestToPayload(&usermodel.GetMyAccountRequest{}) if err != nil { t.Fatalf("encode payload: %v", err) } if _, err := gw.Execute(ctx, usermodel.MessageTypeGetMyAccount, payload, testenv.ExecuteOptions{}); err != nil { t.Fatalf("pre-revoke call failed: %v", err) } // Revoke. internal := testenv.NewBackendInternalClient(plat.Backend.HTTPURL) raw, resp, err := internal.Do(ctx, http.MethodPost, "/api/v1/internal/sessions/"+sess.DeviceSessionID+"/revoke", nil) if err != nil { t.Fatalf("revoke: %v", err) } if resp.StatusCode/100 != 2 { t.Fatalf("revoke status %d body=%s", resp.StatusCode, string(raw)) } // Authenticated requests must now be rejected. Allow up to 2s // for the session-invalidation push frame to propagate to // gateway and close any cached state. deadline := time.Now().Add(2 * time.Second) var lastErr error for time.Now().Before(deadline) { _, lastErr = gw.Execute(ctx, usermodel.MessageTypeGetMyAccount, payload, testenv.ExecuteOptions{}) if lastErr != nil { break } time.Sleep(100 * time.Millisecond) } if lastErr == nil { t.Fatalf("post-revoke call still succeeded; expected rejection") } if !testenv.IsUnauthenticated(lastErr) { t.Fatalf("post-revoke status: expected Unauthenticated, got %v", lastErr) } }