> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ilyama.golain.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Login and authentication

> Authenticate golain with Zitadel OIDC device authorization.

`golain` stores credentials per **profile** at `~/.config/golain/profiles/{name}.json` (mode `0600`). Legacy profiles under `~/.config/platform-tui/profiles/` are still read.

## Device authorization login

```bash theme={null}
golain login                      # default profile
golain login --profile=staging    # named profile
```

The CLI prompts for:

| Prompt               | Example                         |
| -------------------- | ------------------------------- |
| **API URL**          | `https://api.ilyama.golain.io`  |
| **Zitadel endpoint** | `https://dev.zitadel.golain.io` |
| **Client ID**        | From your Zitadel Native app    |

It prints a user code, opens the verification URL, and polls until you approve. Only the **access token** is persisted — re-run login when it expires.

Check identity:

```bash theme={null}
golain whoami
golain profiles
golain logout
```

## Zitadel application setup

Create a **Native** or **User Agent** application with **Device Authorization** enabled (not Web + client secret).

1. Zitadel console → **Projects** → create or select project.
2. **New Application** → type **Native** / **User Agent**.
3. Enable **Device Authorization** grant.
4. Scopes: `openid`, `profile`, `email`.
5. Copy **Client ID** into the login prompt.

Optional: enable **User roles in token** if you rely on custom Zitadel roles.

## Dev and bypass modes

**Local vm-edge stack** defaults (from `infra/deploy/vm-edge/env/apis.vm.env`):

| Setting   | Default                         |
| --------- | ------------------------------- |
| API URL   | `http://localhost:19090`        |
| Zitadel   | `https://dev.zitadel.golain.io` |
| Client ID | `258724445991010309@dev-apis`   |

Override with env vars: `GOLAIN_API_URL`, `GOLAIN_ZITADEL_ENDPOINT`, `GOLAIN_ZITADEL_CLIENT_ID` (legacy `PLATFORM_*` aliases work).

When apis runs with `AUTH_BYPASS=true`, any bearer token works:

```bash theme={null}
GOLAIN_TOKEN=dev GOLAIN_API_URL=http://localhost:19090 golain fleets list
```

## CI without interactive login

For automated jobs against a bypass or service-account endpoint:

```bash theme={null}
export GOLAIN_API_URL=https://api.staging.example.com
export GOLAIN_TOKEN=<token>
golain --output=json fleets list
```

Prefer short-lived tokens and locked-down staging environments for CI.

## Credential file contents

Each profile stores: API URL, Zitadel endpoint, client ID, access token, expiry, and active org/project **context**.

→ [Set context](/tools/platform-tui/context)
