Akanksha-kedia opened a new pull request, #18933:
URL: https://github.com/apache/pinot/pull/18933

   ## Summary
   
   Implements a Trino/Ambari-style **session layer** for the Pinot controller 
UI that addresses several security gaps in the existing Basic auth flow. The 
session layer sits on top of ANY configured `AccessControlFactory` — no changes 
to the auth backend required.
   
   **Problems fixed:**
   
   | # | Problem | Before |
   |---|---------|--------|
   | 1 | Credentials visible in DevTools | Every page navigation sent 
`Authorization: Basic <base64>` in the network tab |
   | 2 | Fake logout | Logout only cleared localStorage; server session 
survived indefinitely |
   | 3 | No session expiry | No inactivity tracking; a tab left open for days 
kept full access |
   | 4 | Credentials in JS memory | `app_state.authToken` held `Basic <base64>` 
(XSS-readable) |
   | 5 | Broker auth from browser | Query page sent `Authorization` header from 
browser directly to broker |
   | 6 | No CSRF protection | Session cookie had no `SameSite` attribute |
   
   **How it works:**
   
   ```
   Browser              Controller                     Broker / ZK
      │  POST /auth/login   │                               │
      │  (form-encoded)     │  hasAccess(SyntheticHeaders)  │
      │ ─────────────────►  │ ──────────────────────────►   │
      │  Set-Cookie:        │  createSession(user, token)   │
      │  Pinot-UI-Session=  │  store in ConcurrentHashMap   │
      │  <token>; HttpOnly  │                               │
      │ ◄─────────────────  │                               │
      │                     │                               │
      │  GET /api/tables    │  SessionAuthenticationFilter  │
      │  Cookie: Pinot-...  │  → getUsername(token) OK      │
      │ ─────────────────►  │  inject Authorization header  │
      │                     │ ──────────────────────────►   │
      │  GET /auth/logout   │  invalidateSession(token)     │
      │ ─────────────────►  │  removes from HashMap         │
   ```
   
   **New files:**
   - `SessionManager.java` — `ConcurrentHashMap` session store with sliding 
TTL; uses atomic `compute()` to eliminate the get→check→remove race condition
   - `SessionAuthenticationFilter.java` — JAX-RS filter at `AUTHENTICATION-10` 
priority; validates HttpOnly cookie; passes through requests with 
`Authorization` header for API backward compat
   - `SessionBasicAuthAccessControlFactory.java` — convenience factory wrapper
   - `PinotSessionLoginResource.java` — `POST /auth/login`, `GET /auth/logout`, 
`GET /auth/session`
   - `SessionManagerTest.java` — unit tests + 50-thread concurrency test
   
   **Cookie construction:** Uses raw `Set-Cookie` header string instead of 
JAX-RS `NewCookie` because JAX-RS 2 `NewCookie` does not support the `SameSite` 
attribute. `SameSite=Strict` blocks cross-site forged requests.
   
   **Frontend changes:**
   - `Models.ts` — `SESSION` enum added to `AuthWorkflow`
   - `axios-config.ts` — SESSION workflow deletes the `Authorization` header; 
cookie sent automatically by browser
   - `AuthProvider.tsx` — reads inactivity timeout from `/auth/info`, checks 
`/auth/session` on page refresh to restore session
   - `App.tsx` — inactivity timer with configurable timeout; 60-second warning 
dialog before auto-logout; calls `/auth/logout` on timeout
   - `Header.tsx` — logout button calls `GET /auth/logout` for server-side 
session invalidation
   - `LoginPage.tsx` — SESSION path POSTs form data to `/auth/login` (no 
`Basic` header in JS memory)
   
   ## Configuration
   
   All defaults preserve existing behaviour. Feature is **opt-in**:
   
   ```properties
   # Enable session-based UI authentication (works with any 
AccessControlFactory)
   controller.ui.session.authentication.enabled=true
   
   # Set false for HTTP-only dev deployments (default: true)
   controller.ui.session.cookie.secure=false
   
   # UI inactivity timeout in seconds (default 300 = 5 min)
   # Server TTL = this + 120s buffer
   controller.ui.session.inactivity.timeout.seconds=300
   ```
   
   ## Test plan
   
   - [ ] `SessionManagerTest` — creation, sliding TTL, logout invalidation, 
50-thread concurrency
   - [ ] `SessionAuthenticationFilter` — unprotected path passthrough, cookie 
validation, Authorization header bypass
   - [ ] `PinotSessionLoginResource` — login/logout/session endpoints
   - [ ] Existing `ControllerAdminApiApplicationTest` and auth tests continue 
to pass unmodified
   - [ ] Manual: open Pinot UI with 
`controller.ui.session.authentication.enabled=true`, verify:
     - No `Authorization` header in DevTools network tab after login
     - Cookie `Pinot-UI-Session` present with HttpOnly flag
     - Logout clears cookie and session is truly gone (server-side)
     - 5-minute inactivity shows warning dialog; auto-logout after countdown
   
   cc @Jackie-Jiang @xiangfu0


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to