queueserver: port the tiled-v0.2.12 auth stack (upstream PR #81) + three upstream fixes - #113
Conversation
Upstream merged 'Updating authenticators from latest in Tiled' (PR NSLS2#81, 2026-08-03), re-aligning bluesky-httpserver's auth with tiled v0.2.12 after ~3 years of divergence. This port keeps the fork wire-compatible with the OIDC login workflows the bluesky-queueserver-api client is adding (its PR NSLS2#62). Adopted wholesale (imports rewritten to queueserver_service.http): authenticators.py (OIDC incl. Entra + proxied + device-code flow, mode flag removed), protocols.py (new; class-type route wiring), database core/orm + pending-sessions migration, schemas additions. app.py wiring, DB auto-upgrade, robust shutdown, and the WebSocket first-message auth handshake are hand-ported into the fork's build_app and split routers. Fork-local behavior re-applied on top: case-insensitive WS auth schemes, WS query-param fallback, async IdP token exchange (upstream's new exchange_code still blocks the event loop), OpenAPI docs on auth routes. Bearer tokens are now accepted on WebSockets (new upstream contract); the WS test asserting they were rejected is updated accordingly. Tests: upstream's new authenticator/OIDC/database test modules ported; OIDC fixtures added to conftest; test server HTTP port overridable via QSERVER_TEST_HTTP_PORT (a foreign container on 60610 otherwise absorbs the whole suite). OpenAPI schema regenerated (additive only). Auth suites green: 28 authenticator + 14 database/OIDC + 12 WS auth + Side-C auth; response-model/shim/drift sentinels 64 passed.
- plan_queue_ops: remove the completed item's UID before registering the re-queued copy in loop mode; the UID dict otherwise grows by one entry per cycle (upstream memory-leak fix). - profile_ops: only evict script-local modules from sys.modules after a startup-script load; unconditional eviction breaks common library modules on Python >= 3.13. Also drops a stray debug print. - profile_ops: fix a shadowed loop variable in annotation processing (type_patterns reused as the loop variable).
The Side-B CI job collects tests/http for the OpenAPI drift test with only the base install present; module-level cryptography/jose/respx imports in conftest broke that collection. The auth/OIDC fixtures now import their deps inside the fixture bodies.
There was a problem hiding this comment.
🟡 Not ready to approve
Verified issues in the new WebSocket/Bearer auth path and some schema/protocol defaults would break or mis-handle authentication at runtime unless corrected.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Pull request overview
Ports the tiled v0.2.12-aligned authentication stack (OIDC incl. Entra/proxied/device-code), plus associated DB/schema and WebSocket auth changes, into queueserver_service to keep this fork wire-compatible with upstream and upcoming bluesky-queueserver-api OIDC workflows.
Changes:
- Add tiled-aligned authenticator protocols and expanded OIDC/Entra/proxied-auth flows (incl. device-code) with new DB persistence for pending sessions + per-session state.
- Update HTTP/WebSocket auth handling (including first-message WS auth handshake) and refresh OpenAPI/schema/docs accordingly.
- Port three upstream functional fixes (loop-mode UID dict leak, Py>=3.13 sys.modules eviction guard, annotation loop var shadowing) and extend test/fixture/dev-deps coverage.
File summaries
| File | Description |
|---|---|
| shared-schema/queueserver_service.openapi.json | OpenAPI schema updates for new auth/session fields. |
| backend/queueserver_service/tests/http/test_oidc_proxied_authenticators.py | New tests for proxied OIDC OAuth2 schema/token extraction. |
| backend/queueserver_service/tests/http/test_oidc_authenticators.py | New tests for OIDC authenticator caching/decoding/properties. |
| backend/queueserver_service/tests/http/test_database.py | New tests for new Principal/Session DB fields and helpers. |
| backend/queueserver_service/tests/http/test_authenticators.py | Expanded auth tests (LDAP/OIDC/Entra/token decoding/scope helpers). |
| backend/queueserver_service/tests/http/test_auth_for_websockets.py | Extended WS auth tests including Bearer forwarding + first-message handshake. |
| backend/queueserver_service/tests/http/conftest.py | New OIDC + SQLite fixtures; configurable HTTP test server port. |
| backend/queueserver_service/requirements-dev.txt | Add dev deps needed for new auth tests (cryptography/respx). |
| backend/queueserver_service/queueserver_service/manager/profile_ops.py | Py>=3.13 sys.modules eviction guard + annotation loop var fix. |
| backend/queueserver_service/queueserver_service/manager/plan_queue_ops.py | Fix loop-mode UID dict growth by removing completed UID before re-queue. |
| backend/queueserver_service/queueserver_service/http/server.py | Cache lazily-created app to avoid repeated factory calls. |
| backend/queueserver_service/queueserver_service/http/schemas.py | Add device-code schemas + new Principal/Session fields. |
| backend/queueserver_service/queueserver_service/http/routers/console.py | Add WS first-message auth handshake and consistent close codes. |
| backend/queueserver_service/queueserver_service/http/protocols.py | New authenticator protocol base classes + session state DTO. |
| backend/queueserver_service/queueserver_service/http/database/orm.py | Add session state JSON + PendingSession ORM model. |
| backend/queueserver_service/queueserver_service/http/database/migrations/versions/a1b2c3d4e5f6_add_pending_sessions.py | New migration for pending sessions + session state column. |
| backend/queueserver_service/queueserver_service/http/database/core.py | Add pending-session lookups + principal creation helper; bump required revision. |
| backend/queueserver_service/queueserver_service/http/config_schemas/service_configuration.yml | Update authenticator import-path documentation/examples. |
| backend/queueserver_service/queueserver_service/http/authenticators.py | Major port of tiled-aligned OIDC/Entra/proxied auth + async token exchange. |
| backend/queueserver_service/queueserver_service/http/authentication.py | Major refactor: token decoding, device-code routes, WS auth support, session state embedding. |
| backend/queueserver_service/queueserver_service/http/app.py | Route wiring driven by authenticator class type; automatic DB upgrade; robust shutdown. |
| backend/queueserver_service/pyproject.toml | Add runtime dep (cachetools) + uv dev dependency group. |
| backend/queueserver_service/docs/source/http/usage.rst | Document OIDC browser/device flows; test-port override note. |
| backend/queueserver_service/docs/source/http/configuration.rst | Document OIDC/Entra authenticator configuration examples. |
| backend/queueserver_service/bluesky-httpserver/bluesky_httpserver/init.py | Shim mapping updated to include protocols. |
| .gitignore | Ignore local .reflow2/ directory. |
Review details
Suppressed comments (2)
backend/queueserver_service/queueserver_service/http/authentication.py:574
authenticate_websocket_first_message()callsget_current_principal()directly but does not decodeaccess_tokenintodecoded_access_token, so Bearer-token auth via the first-message handshake will not work (and the defaultDepends(...)value can cause type errors).
security_scopes = SecurityScopes(scopes=[])
try:
return get_current_principal(
request=websocket,
security_scopes=security_scopes,
access_token=access_token,
api_key=api_key,
settings=settings,
authenticators=authenticators,
api_access_manager=api_access_manager,
)
backend/queueserver_service/docs/source/http/configuration.rst:369
- This configuration example uses the shim import path
bluesky_httpserver.authenticators:EntraAuthenticator, but the rest of this repo’s docs/config schema usequeueserver_service.http.authenticators:.... Using the canonical in-repo path here would avoid confusing users and keep examples consistent.
- provider: entra
authenticator: bluesky_httpserver.authenticators:EntraAuthenticator
args:
- Files reviewed: 25/27 changed files
- Comments generated: 7
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
8608bf3 to
22db2c1
Compare
- Decode Bearer tokens explicitly on both direct WebSocket auth paths: calling get_current_principal() outside FastAPI left decoded_access_token at its Depends(...) default (a truthy sentinel), which broke WS Bearer auth. Invalid/expired tokens now fail closed; regression asserts added to the WS precedence test. - Fix decoded_access_token annotation (Optional[dict]) and the invalid 'Principal or None' return annotations (Optional[...], 3 sites). - Replace mutable defaults: UserSessionState.state and Session.state use default_factory; schema regenerated (default no longer emitted). - Docs: use the canonical queueserver_service.http.authenticators paths in configuration examples (3 sites); fix 'acheived' typo.
|
Also addressed the two suppressed review comments in c7280ce:
|
Ports bluesky/bluesky-httpserver#81 (merged 2026-08-03), which re-aligns the auth stack with tiled v0.2.12 after ~3 years of divergence, keeping this fork wire-compatible with the OIDC login workflows bluesky-queueserver-api is adding (bluesky/bluesky-queueserver-api#62).
Adopted from upstream (imports rewritten to queueserver_service.http):
Fork behavior re-applied on top: case-insensitive WS auth schemes, WS query-param fallback, OpenAPI docs on auth routes, and the async IdP token exchange (upstream's new exchange_code is async but still calls blocking httpx.post — worth offering back upstream). Contract note: Bearer tokens are now accepted on WebSockets, matching upstream; the committed OpenAPI schema change is additive only.
Also ports the three functional fixes this fork was missing from bluesky-queueserver v0.0.25: the loop-mode UID-dict memory leak, the Python >= 3.13 sys.modules eviction guard in profile_ops, and a shadowed loop variable in annotation processing. An audit of all other upstream changes since April found them already present or not applicable.
Test-infra: the HTTP test-server port is overridable via QSERVER_TEST_HTTP_PORT; new OIDC test fixtures + upstream's authenticator/OIDC/database test modules; dev deps for local runs added as a uv dependency group.
Tests: 28 authenticator + 14 database/OIDC + 12 WebSocket-auth tests green; API-compat tests green against the real bluesky-queueserver-api client; response-model/shim/OpenAPI-drift sentinels 64 passed; 73 profile-ops + 36 queue-ops tests green. LDAP authenticator tests run in CI (need the LDAP container).