When a user spawns a container, the container is accessible at a known port on the host. Anyone who discovers that port can access the container directly, bypassing the Flask app entirely. Additionally, if a second user logs in to an already active container, there is no mechanism to invalidate the first user's session.
This solution enforces sessions inside the container itself, so it doesn't matter how a request reaches it, the container will always reject unauthenticated or stale requests.
Two small additions to the container:
A minimal Python HTTP server that runs on 127.0.0.1:9999 inside the container.
It is never reachable from outside — it only talks to the container nginx internally.
It does two things:
- Acts as a login proxy —> when a user logs in, the container nginx routes the login
request through the sidecar instead of directly to the auth daemon. The sidecar forwards
the request, and if the auth daemon returns a success, it generates a secure random token,
stores it in memory, and injects a
Set-Cookieheader into the response before returning it to the browser.
same is done for the logout -> when a user close the web page or request a logout, nginx routes to the sidecar -> sidecar delete the session token and call the auth client logout
- Validates sessions — on every request to any protected resource, the container nginx
calls the sidecar's
/validateendpoint as a subrequest. The sidecar compares the token from the browser's cookie against the one stored in memory. If they match, the request proceeds. If not, the container nginx blocks it with a401.
The container nginx is updated to:
- Route
/api/v1.0/local_login/through the sidecar (login proxy) instead of the flask app. - Route
/api/v1/authenticate/logoutthrough the sidecar, then auth client - Route
/api/v1/authenticate/loginthrough the sidecar, then auth client - Add an
auth_requestcheck to every other location, pointing to the sidecar's/validateendpoint. - Return a
401or403JSON response for any request that fails validation.
| Scenario | Result |
|---|---|
| User knows the port and bypasses Flask | Container nginx fires auth_request → no cookie → 401 blocked |
| User tries to access an active container without logging in | Same as above — 401 |
| A second user logs in to an already active container | Sidecar overwrites the stored token — first user's cookie immediately becomes invalid |
| User tampers with their cookie | secrets.compare_digest rejects any value that doesn't match exactly |
| Fresh container, nobody logged in yet | _token is None — every request returns 401 until a real login occurs |
The host Flask app and host nginx require zero changes. The host nginx continues to proxy to the container port as before. The enforcement is entirely internal to the container.
- The host nginx configuration
- The Flask application
- The internal auth daemon or any other daemon inside the container
- Container port mappings
- Any other part of the existing infrastructure