Native hosted login
ENG-2758 adds API2 ownership of
GET /accounts/auth/workos and its authorization-code callback. The server
stage is deployed in US and EU; the caller stage moves /login, /signup,
password reset and same-region regional-auth entry points from Rails to API2.
Headless auth, direct invitation callbacks, external token contracts and
WorkOS webhook identity sync remain on Rails. New membership/employee
provisioning on this callback has since moved to API2 — see
native invite acceptance.
Contract
- Keep the pre-auth state, PKCE verifier and sanitized same-app redirect in the existing Rack session table. Store only the private Rails session ID and reject missing, forged or older-than-15-minute attempts.
- Exchange each WorkOS code once with a three-second timeout and no retries. Seal the response in the Ruby-compatible AES-256-GCM envelope so retained Rails refresh/logout remains valid.
- Resolve an account by exact provider identity or case-insensitive email while holding a transaction advisory lock. Fail closed if those keys identify two accounts. Create tenantless self-serve accounts, but never invent a local organization membership in this stage.
- For an organization-scoped authentication response, require a kept local membership. Preserve its status, role, scopes and WorkOS membership ID; this stage never provisions or repairs identity records. (Superseded by native invite acceptance, which provisions and heals memberships on this callback.)
- Mint Rails’ masked global CSRF token, store its real token in the Rack session
and set the shared readable
XSRF-TOKENcookie so retained Rails mutations continue to pass forgery protection after a native login. - Rotate the Rack cookie and persisted row atomically with compare-and-swap. Concurrent callbacks may produce one success only. A local failure rolls back account, membership and session changes.
- Return only generic auth failures. Logs contain an event name, never email, code, state, cookie, tokens, redirect URI or serialized session data.
- When email-first auth requests enterprise SSO, resolve the first active WorkOS connection for the login-hint domain and authorize with its connection ID. Missing, inactive and failed lookups fall back to hosted AuthKit, matching the retained Rails behavior.
- Treat WorkOS authorization options as provider-specific.
screenHintis valid for hosted AuthKit only and must not be sent with an explicit or discovered connection ID. Exercise the installed WorkOS SDK’s URL builder in tests when changing these options; a permissive client mock does not validate the provider contract.
Focused tests exercise forged/expired/replayed attempts, transactional rollback, tenantless creation, identity conflicts, Rails-readable sessions and concurrent single-use completion. Ruby OpenSSL independently unmasks a generated native CSRF token and matches Rails’ global-token HMAC.
Monitoring
Every hosted-login transition emits the auth.hosted_login.events Sentry
counter with low-cardinality event, flow, service.name and cloud.region
attributes. Failures also emit an error-level log with a stable
rulebase.fingerprint and an error type. Do not attach the raw exception or
request query: provider errors and callback URLs can contain email addresses,
authorization codes or state.
CloudWatch log metric filters named native-hosted-login-start-failed watch the
US and EU API2 log groups for native_hosted_login_start_failed. Their regional
alarms fire on the first failure in a one-minute period and notify the confirmed
rulebase-prod-infra-alerts-<region> SNS topic:
fc-rulebase-api2-prod-5whj12su-native-hosted-login-start-failedfc-rulebase-api2-prod-eu-9rfp06k-native-hosted-login-start-failed
The regional API2 load-balancer alarms for ELB 5xx responses, target 5xx
responses, latency and unhealthy hosts also include the confirmed
rulebase-prod-infra-alerts-<region> action. When reviewing an alarm, verify
its destination has a confirmed subscription; an enabled alarm attached only
to an empty SNS topic changes state without notifying anyone.
Keep this route-level signal even when API2 has general load-balancer alarms. Hosted login can fail for one authentication path while the service remains healthy and other login paths continue to succeed.
Rollout
At September 3 19:00 UTC, fresh US/EU API2 tasks contained
RULEBASE_API2_BASE_URL, the matching app origin/CORS setting and the existing
WorkOS client, secret and 32-byte cookie password. The user confirmed
https://api2.rulebase.co/accounts/auth/workos/callback and
https://eu.api2.rulebase.co/accounts/auth/workos/callback are registered in
the regional WorkOS redirect allowlists.
Deploy the caller stage, then require an actual successful tenantless login, existing-membership login and enterprise SSO login in each region, callback replay rejection, native logout and organization switch, then 24 hours without a new hosted-login failure. Local provisioning now has a native owner (native invite acceptance); the direct invite-email callback still lands on Rails because it carries no API2 state or PKCE verifier. Roll back callers first; keep both server implementations during observation.