# Authentication

> Configure how self-hosted Menace Voice authenticates users — the default local provider, or Stack Auth for social login

Self-hosted Menace Voice ships with a built-in **local** authentication provider (email + password, backed by a signed JWT). This is the default and needs no external service.

To offer social logins (Google and other providers), you can delegate sign-in to **[Stack Auth](https://stack-auth.com)**. Enabling it is a **runtime** configuration change — set a few environment variables and restart. The prebuilt `dograhai/dograh-api` and `dograhai/dograh-ui` images work as-is; you do **not** need to rebuild or build from source.

<Note>
The active provider is `local` by default. When the deployment `.env` contains a Hexclave/Stack **project id and secret server key**, the API enables `stack` automatically (`AUTH_PROVIDER=local` still forces local). The frontend discovers the provider — and, for Stack, its public client config — at runtime from the backend's `/api/v1/health` response, so the browser bundle never needs Stack values baked in at build time.
</Note>

## How it works

1. The backend reads `AUTH_PROVIDER` and the Stack settings from its environment.
2. When `AUTH_PROVIDER=stack`, `/api/v1/health` returns the **public** Stack client config (project id + publishable client key).
3. The UI fetches that at runtime and initializes the Stack SDK in the browser.
4. The **secret server key** is used only server-side (by the backend and the UI's server runtime) and is never sent to the browser.

## Prerequisites

A Stack Auth project. Create one in the [Stack Auth dashboard](https://app.stack-auth.com) and configure the social login providers you want to offer.

## Step 1 — Collect your Stack credentials

From your project in the [Stack Auth dashboard](https://app.stack-auth.com), gather:

| Value | Sensitivity |
|---|---|
| **Project ID** | Public |
| **Publishable client key** | Public (safe to expose in the browser) |
| **Secret server key** | Secret — keep server-side only |
| **API base URL** | Public. For Stack's hosted service this is `https://api.stack-auth.com` |

## Step 2 — Set them in the deployment `.env`

Put the values in the `.env` next to `docker-compose.yaml` (the file `setup_remote.sh` / `setup_local.sh` created — **not** `api/.env`, which only applies to local `uvicorn`). Compose interpolates that file into both the `api` and `ui` containers; you do not need to edit `docker-compose.yaml`.

```bash .env
HEXCLAVE_PROJECT_ID="<your-project-id>"
HEXCLAVE_SECRET_SERVER_KEY="<your-secret-server-key>"
# Optional; set only to force a provider. Unset + keys above enables stack.
# AUTH_PROVIDER=stack
# Optional; newer Hexclave projects often omit it
# STACK_PUBLISHABLE_CLIENT_KEY="<your-publishable-client-key>"
# Optional; API defaults to https://api.hexclave.com
# STACK_AUTH_API_URL="https://api.stack-auth.com"
```

Legacy `STACK_AUTH_PROJECT_ID` / `STACK_SECRET_SERVER_KEY` names still work.

<Note>
The UI does **not** need the project id or publishable client key in its own env — it receives those from the backend at runtime via `/api/v1/health`. The secret server key is passed to `ui` as well because SSR pages and `/handler/*` call Stack server-side.
</Note>

## Step 3 — Restart and verify

Recreate the containers so they pick up the new environment:

```bash
# Local Docker install
docker compose up -d

# Remote install created by setup_remote.sh
./remote_up.sh
```

Confirm the backend reports the active provider and the public client config:

```bash
curl -s http://localhost:8000/api/v1/health
# expect: "auth_provider":"stack", plus "stack_project_id" and "stack_publishable_client_key"
```

Then open the UI. The sign-in page should now present your configured Stack Auth social login options instead of the local email/password form.

## Environment variable reference

| Variable | Service | Secret | Notes |
|---|---|---|---|
| `AUTH_PROVIDER` | `api` | — | `stack` or `local`. Unset + project id + secret enables stack. `local` always wins |
| `HEXCLAVE_PROJECT_ID` / `STACK_AUTH_PROJECT_ID` | `api` | No | Project ID; served to the UI at runtime |
| `STACK_PUBLISHABLE_CLIENT_KEY` | `api` | No | Publishable key; served to the UI at runtime. Optional for newer Hexclave projects |
| `HEXCLAVE_SECRET_SERVER_KEY` / `STACK_SECRET_SERVER_KEY` | `api` + `ui` | **Yes** | Server-side only — never exposed to the browser |
| `STACK_AUTH_API_URL` / `HEXCLAVE_API_URL` | `api` | No | REST API base URL. Defaults to `https://api.hexclave.com` |

<Warning>
`HEXCLAVE_SECRET_SERVER_KEY` / `STACK_SECRET_SERVER_KEY` is the only secret here. Keep it out of any client-visible config and never bake it into an image. The project ID and publishable client key are public by design — the backend deliberately serves them to the browser so Stack can initialize at runtime.
</Warning>

## Reverting to local auth

Remove the variables above (or set `AUTH_PROVIDER=local`) and restart. The UI detects `local` from the backend at runtime and falls back to the built-in email/password flow — no rebuild required.
