Skip to main content
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

ClientTypeUse
nkama-mobilepublic, PKCEMobile/web apps. Authorization Code + PKCE.
nkama-apibearer-onlyThe audience the resource server requires.
nkama-adminconfidentialBackend-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:
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)
The password grant (ROPC) is for testing only and is disabled on the production client. Real apps must use Authorization Code + PKCE.

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.