Bluesky login-brokerยถ
OIDC to Bluesky-PDS app-password broker (variant A+ per requirement 013, web-app-bluesky per-role notes).
The broker sits behind web-app-keycloakโs SSO-proxy sidecar and in front of the
official @bluesky-social/social-app web client. On a userโs first
OIDC-authenticated visit, the broker:
Looks up the Keycloak user via the Admin REST API. The service-account credentials are mounted as env, see
KC_ADMIN_*.Provisions a Bluesky PDS account via
com.atproto.server.createAccountif no encrypted app-password is recorded on the user yet, encrypts the synthesised app-password with AES-256-GCM, and stores the ciphertext as thebluesky_app_password_encuser attribute.Decrypts the stored app-password in-process and exchanges it for a PDS session via
com.atproto.server.createSession.Renders an HTML handoff page that drops the resulting session JWTs into
localStorage["BSKY_STORAGE"](the canonicalsocial-appstorage key), sets a short-livedbsky_handoff_done=1cookie, and redirects to/.
For subsequent requests carrying that cookie, the broker reverse-
proxies to the social-app upstream so the user appears to log in
to Bluesky purely via Keycloak SSO without ever seeing the
synthesised app-password.
Required environmentยถ
Variable |
Purpose |
|---|---|
|
TCP port to listen on (default |
|
Reverse-proxy upstream ( |
|
Public Bluesky PDS base URL ( |
|
In-stack PDS URL for server-side XRPC calls ( |
|
Suffix for synthesised handles ( |
|
Optional invite code for gated PDS deployments. |
|
Keycloak base URL ( |
|
Realm of the brokerโs service account (typically the same as user realm). |
|
Service-account client ID. |
|
Service-account client secret. |
|
Realm where end-user accounts live (typically same as admin realm). |
|
base64-encoded 32 random bytes; AES-256-GCM key. |
|
Override the cookie name (default |
|
Cookie lifetime in seconds (default |
|
If |
Forwarded identityยถ
The upstream oauth2-proxy MUST set X-Forwarded-User (or
X-Forwarded-Preferred-Username) and X-Forwarded-Email on every
request that reaches the broker. Without X-Forwarded-User, the
broker returns HTTP 401, there is no anonymous fallback by design.
Failure modesยถ
PDS unreachable: the broker bubbles up the createAccount or createSession failure and the user sees an HTML error page on the handoff route. Re-trying the visit after PDS recovery completes the handoff.
Encrypted attribute decrypt failure: indicates a key mismatch between the SPI and the broker. The broker rejects the request with HTTP 500 rather than risk silently re-provisioning a fresh PDS account that loses the userโs existing posts. Recovery: rotate the key and clear the attribute (manual op for now, key rotation is in the doc 013 Future Hardening section).
social-app upstream error: the broker forwards the upstreamโs error response.