Authentication and tokens
Concierto has three kinds of tokens. One each for the browser, the CLI, and the daemon. When to use which.
Concierto has three kinds of tokens, one for each context: the browser Web UI, the command line and scripts, and the daemon. All three represent the same you, but their scopes and lifetimes differ.
The three tokens
| Token | Format | Where it's used | Lifetime |
|---|---|---|---|
| JWT cookie | concierto_auth cookie (HttpOnly) | Web browser | 30 days |
| Personal access token (PAT) | Prefixed with nst_ (or legacy mul_) | CLI, scripts, direct API calls | No expiry by default; when you create one via the API you can pass expires_in_days. PATs minted by concierto login's browser flow expire after 90 days |
| Daemon token | Prefixed with mdt_ | Daemon-to-server communication | Managed by the daemon itself |
PATs minted before the Concierto rebrand use the mul_ prefix and continue to work indefinitely, only the prefix on newly minted tokens changed. You don't need to regenerate anything.
In day-to-day use you'll only touch the first two directly. The daemon token is created and refreshed automatically by concierto daemon login, you don't have to think about it.
What each token can hit
| API route | JWT cookie | PAT | Daemon token |
|---|---|---|---|
/api/user/* (user-level actions) | ✓ | ✓ | ✗ |
/api/workspaces/:id/* (workspace-level) | ✓ | ✓ | ✗ |
/api/daemon/* (daemon-only) | ✗ | ✓ | ✓ |
WebSocket /ws (real-time push) | ✓ (cookie) | ✓ (authenticates via first message) | ✗ |
A PAT can hit almost anything, it represents "the full you." A daemon token can only do what the daemon needs: fetch tasks and report results.
Both can hit /api/daemon/*, but their scopes differ. A PAT represents an entire user. Once authenticated, it can see every workspace you belong to. A daemon token is pinned to a single workspace at creation time and can only touch resources in that workspace. In production, run your daemon with a daemon token. Don't take the shortcut of using a PAT, or you'll be granting far more privilege than the daemon needs.
Logging in
Email + verification code
- Enter your email; the server sends a 6-digit code.
- Enter the code; the server issues a JWT cookie (browser) or exchanges it for a PAT (CLI).
Self-hosting operators, take note: keep CONCIERTO_DEV_VERIFICATION_CODE empty on public deployments. If you enable a fixed local test code, anyone who can request a code can sign in with that value while APP_ENV is non-production. See Self-host auth configuration.
Google OAuth
Click Sign in with Google and go through the standard OAuth callback. Self-hosting requires GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and the redirect URI to be configured, see Self-host auth configuration.
How concierto login authorizes the CLI
The CLI's browser login is a small OAuth-style handshake:
concierto loginstarts a one-shot HTTP listener on a random local port and opens your browser at the web app's login page, carrying a callback URL and a CSRF state value.- If you already have a browser session, you land directly on the Authorize CLI page: "Allow the CLI to access NSTACK AI · Concierto as you@example.com". If not, you sign in first (email code or Google), then see the same page. Use a different account lets you switch identities before authorizing.
- Clicking Authorize makes the web app issue a short-lived token and redirect the browser to the CLI's local callback. The CLI validates the CSRF state, then exchanges the token for a 90-day PAT named
CLI (<hostname>)and stores it in~/.concierto/config.json. - The browser shows "Authentication successful, you can close this tab", and the terminal continues: the CLI discovers your workspaces and suggests
concierto daemon start.
The callback only ever points at localhost or a private (RFC 1918) address, and the state value is validated before the token is accepted, so another site can't trick your browser into handing a token to a listener it controls.
Because the authorization mints a separate PAT, revoking it (Settings → Personal Access Tokens → the CLI (<hostname>) entry) signs out that machine's CLI without touching your browser session or other devices.
Creating, viewing, and revoking a PAT
Creating a PAT can be done two ways:
- Web UI: Settings → Personal Access Tokens → New token
- CLI:
concierto logincreates one automatically if there's no local PAT yet
The full PAT is displayed exactly once when it's created. After you refresh or close the dialog, you won't be able to see it again.
Concierto stores only the hash of the PAT in the database, not even the server can retrieve the original. Copy and save it immediately. If you lose it, your only option is to revoke it and create a new one.
Viewing existing PATs (name, creation time, last-used time, not the full token) lives under Settings → Personal Access Tokens.
Revoking a PAT: click Revoke in the list. Revocation takes effect immediately, the next request made with that PAT will be rejected with a 401.
Logging out only deletes the local token
When you run concierto auth logout or click log out in the Web UI:
- The local token is cleared, the CLI removes the PAT from
~/.concierto/config.json; the browser deletes the cookie. - The PAT is still valid on the server. If someone obtained your PAT before you logged out (for example, by copying it to another machine), they can still use it.
If you suspect your PAT has leaked, don't just log out. Go to Settings → Personal Access Tokens and revoke the token. Only revocation invalidates a leaked token immediately.
Next steps
- CLI command reference, authentication is automatic for every CLI command
- Self-host auth configuration. How to configure email, OAuth, and signup allowlists when self-hosting
- Daemon and runtimes, where the daemon token comes from