Skip to main content

Local development authentication

The local dev stack runs with session-based authentication by default. When you start ./dev-tail.sh, the API container picks up /auth-config/auth.yaml, which is bind-mounted from .dev-auth.yaml at the repo root.

This means the login flow works end-to-end out of the box: visit http://localhost:3000, click "Dev stub login", and pick a user.

The committed dev fixtures​

.dev-auth.yaml defines three test users that every contributor shares:

  • alice — admin of project:tomcat, member of project:httpd. Use this user for most workflows; you'll see workspace switching, role- scoped UI, and the standard "logged in as a project member" experience.
  • bob — emeritus, no workspace memberships. Useful for testing the deny path: bob's login should be rejected with a "no workspaces available" error rather than completing successfully. If you find a way for bob to land on the home page, that's a bug.
  • site_admin_1 — listed in site_admins at the bottom of the file, so this user logs in as a cross-workspace site administrator. Use this to test admin-only views and operations.

These fixtures are committed deliberately. They have no real secrets (the dev_stub provider grants login on uid alone with no credential check) and sharing them keeps everyone testing the same code paths.

Customizing for your own testing​

If you need different users — say, to mirror your organization's LDAP UIDs while testing membership lookup, or to add a fourth role that doesn't exist in the shared fixture — copy the file:

cp .dev-auth.yaml .dev-auth.local.yaml
$EDITOR .dev-auth.local.yaml

.dev-auth.local.yaml is gitignored, so personal edits don't risk ending up in a commit.

To make the dev stack use your local copy, edit the compose file's volumes line for the api service to point at .dev-auth.local.yaml instead, then re-run ./dev-tail.sh. (A future improvement: have dev-tail.sh prefer a .dev-auth.local.yaml if one exists.)

Production deployments​

The committed .dev-auth.yaml is never appropriate for production. The dev_stub provider grants admin access via uid alone with no credential verification — anyone who can reach /auth/login/dev_stub becomes whichever user they ask to be.

For production, see docs/examples/auth.example.yaml for a template that wires up real providers (ASF, Google, Microsoft, GitHub). Your deployment process should:

  1. Mount the production auth.yaml at a path of your choosing (typically from a secret manager, not the filesystem).
  2. Set AUTH_CONFIG_PATH to point at it.
  3. Either remove dev_stub from auth.providers or set enabled: false for that entry. The dev_stub provider should never be enabled in any environment that's reachable from the public internet.
  4. Set legacy_firebase_enabled: false once your migration off Firebase is complete.

Disabling auth locally​

If you want to run the local stack without auth — for instance, while poking at code paths that don't need an authenticated user — set the frontend's auth provider to mock in webapp/packages/config/environments/local.js:

auth: {
provider: 'mock',
},

The backend still mounts the auth routes (because the auth.yaml is still bind-mounted), but the frontend won't try to use them; it uses the mockAuth implementation that grants instant local-dev-user access with no login page. Switch back to 'session' to re-enable.

Troubleshooting​

"Dev stub login" button missing on /login. The frontend probes /auth/providers to decide which buttons to render. If the API container started without AUTH_CONFIG_PATH set, that endpoint returns an empty list. Restart the api container:

docker compose restart api

Login completes but lands back on /login. The session cookie was set, but the frontend isn't recognizing it. Check that webapp/packages/config/environments/local.js has auth: { provider: 'session' } — 'mock' and 'firebase' will both ignore the session cookie.

{"detail":"Not Found"} after picking a user. The OAuth callback redirected to /login against the wrong host. Check webapp/packages/api/user-service/routes_auth.py — the redirect target should be prefixed with FRONTEND_URL.

bob lands on the home page. This shouldn't happen — bob has no workspace memberships and the auth callback should reject the login. If you see this, check that legacy_firebase_enabled: true isn't short-circuiting the workspace check, and file an issue.