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

# Authentication

> OpenID Connect via Keycloak — obtaining and using a bearer token.

NKAMA does not issue its own tokens. It is an **OAuth2 resource server**: it trusts access
tokens issued by **Keycloak** (the `nkama` realm at `https://auth.yvnn.is`). Every secured
endpoint expects:

```
Authorization: Bearer <access_token>
```

## What the API validates

* **Signature & issuer** — the token must be signed by the realm and carry
  `iss = https://auth.yvnn.is/realms/nkama`.
* **Audience** — the token must include the `nkama-api` audience (the `nkama-mobile`
  client injects it).
* **Expiry** — expired tokens are rejected; refresh and retry.
* **Roles** — realm roles (`TENANT`, `OWNER`, `MANAGER`, `ADMIN`) become Spring authorities
  and gate endpoints. `org_id` scopes data to one organization.

## Clients

| Client         | Type         | Use                                                 |
| -------------- | ------------ | --------------------------------------------------- |
| `nkama-mobile` | public, PKCE | Mobile/web apps. Authorization Code + PKCE.         |
| `nkama-api`    | bearer-only  | The audience the resource server requires.          |
| `nkama-admin`  | confidential | Backend-only service account (not for app clients). |

### Mobile / web (Authorization Code + PKCE)

```
discovery   = https://auth.yvnn.is/realms/nkama/.well-known/openid-configuration
client_id   = nkama-mobile
scopes      = openid profile email
pkce        = S256 (required)
```

Run the standard PKCE flow against the discovery document; the resulting access token is the
bearer you send to the API.

### Scripts / testing

For non-interactive testing you can exchange credentials at the token endpoint directly:

```bash theme={null}
ACCESS_TOKEN=$(curl -s \
  -d grant_type=password -d client_id=nkama-mobile -d scope=openid \
  --data-urlencode username="+241…" \
  --data-urlencode password="<password>" \
  https://auth.yvnn.is/realms/nkama/protocol/openid-connect/token | jq -r .access_token)
```

<Warning>
  The password grant (ROPC) is for testing only and is disabled on the production client.
  Real apps must use Authorization Code + PKCE.
</Warning>

## Public (no token) endpoints

Sign-up (`POST /api/v1/registration/**`), password reset
(`POST /api/v1/account/password-reset/**`), the legal versions
(`GET /api/v1/legal/**`) and vendor webhooks (`POST /webhooks/**`) are deliberately
pre-authentication. Everything else requires a bearer token.
