# Sign-in with ZITADEL or Cognito

> Choose the identity provider for the console, set the values Douklar reads, and map your admin group.

Douklar has no login form of its own. Sign-in comes from one identity
provider per deployment, chosen with `AUTH_MODE`:

| `AUTH_MODE` | Who signs people in | Use it for |
|---|---|---|
| `zitadel` | ZITADEL: bundled by `./install.sh local`, or one you run elsewhere | The default; local and self-hosted deployments |
| `cognito` | Amazon Cognito managed login | Teams that already keep users in a Cognito user pool |
| `none` | Nobody: one implicit local admin, no login screen | One person on one machine. The backend refuses it outside a local deployment |

Users, passwords, MFA and passkeys are managed in the provider's own console,
not in Douklar.

## ZITADEL

`./install.sh local` starts ZITADEL in Docker, creates the project, role and
sign-in client, and writes the values to `.env`. To use a ZITADEL you already
run, set:

```ini
AUTH_MODE=zitadel
ZITADEL_ISSUER=https://auth.example.com
ZITADEL_CLIENT_ID=...
ZITADEL_REDIRECT_URI=https://app.example.com/api/auth/oidc/callback
ZITADEL_PROJECT_ID=...
ZITADEL_ADMIN_ROLES=platform-admins
```

`ZITADEL_CLIENT_SECRET` is needed only for a confidential client. The env
wizard's `external-zitadel` profile writes the full set; a complete command is
in [Use an external PostgreSQL](/docs/douklar/external-postgresql#amazon-rds).

A user is an admin when their token carries one of the roles in
`ZITADEL_ADMIN_ROLES` (default `platform-admins`). Grant the role in the
ZITADEL console. The account menu's "Manage account in ZITADEL" link opens the
provider's own page for password, MFA and passkeys.

## Amazon Cognito

The one-time work in the AWS console:

1. Create a user pool.
2. Create a domain under *App integration, Domain*. That hostname is
   `COGNITO_DOMAIN`.
3. Create an app client with the authorization code flow, PKCE and the
   `openid`, `profile` and `email` scopes. Add
   `https://app.example.com/api/auth/oidc/callback` as a sign-in redirect URI
   and `https://app.example.com/` as a sign-out redirect URI, exactly as in
   `.env`.
4. Create the admin group (`platform-admins` by default) and add the first
   operator to it.

Then set:

```ini
AUTH_MODE=cognito
COGNITO_REGION=us-east-1
COGNITO_USER_POOL_ID=us-east-1_XXXXX
COGNITO_CLIENT_ID=...
COGNITO_DOMAIN=tenant.auth.us-east-1.amazoncognito.com
COGNITO_REDIRECT_URI=https://app.example.com/api/auth/oidc/callback
COGNITO_LOGOUT_REDIRECT_URI=https://app.example.com/
COGNITO_ADMIN_GROUPS=platform-admins
```

Douklar reads `cognito:groups` from the verified tokens. After a group change,
sign in again to get new tokens.

## Roles

Douklar has three fixed roles, mapped from the provider's groups or roles:
`admin`, `operator` and `viewer`. The highest mapped role wins.
[Install locally](/docs/douklar/install#roles) lists what each one can do.

## Check the setup

```bash
make auth-check
```

It reads `.env`, reaches the provider's discovery document, and prints the
exact mismatch when the issuer, client or redirect URI differ.

| Symptom | Fix |
|---|---|
| Login bounces back after the provider | The redirect URI differs from the registered one; `make auth-check` shows both |
| `invalid_client` | The client id is wrong or the client was deleted; create one and update `.env` |
| Signed in, but no admin menus | The user lacks the admin role or group; grant it and sign in again |
| Cognito login page returns 404 | `COGNITO_DOMAIN` is not the domain set under *App integration, Domain* |

Source: https://douklar.app/docs/douklar/sign-in-zitadel-or-cognito (Douklar docs, last checked 2026-10-18)
