Authentication for Local Development
This guide covers the Keycloak configuration used by the local Nix/process-compose stack. See Local Development Setup for startup commands and Portless naming.
Keycloak Setup
make up-deps starts Keycloak and applies the realm configuration with OpenTofu after Keycloak becomes healthy. The definitions live in tf/modules/keycloak-realms/; they are not imported from a dev/keycloak/ directory.
Keycloak Admin Console
For a checkout named lana-bank:
- URL: http://keycloak.lana-bank.localhost:1355
- Master realm username:
admin - Master realm password:
admin
Use $LANA_KEYCLOAK_PUBLIC_URL for your worktree's browser-facing URL. http://localhost:8081 applies only in fixed-port mode.
Realms
The local stack explicitly configures these realm names:
| Realm | Purpose | Used by |
|---|---|---|
main-internal | Administrative users | Admin Panel and admin API |
main-customer | Bank customers | External customer clients and customer API |
main-partner | Partner users | Partner Portal and partner API |
Deployed instances normally derive realm names as <instance_name>-internal, <instance_name>-customer, and <instance_name>-partner; operators can override them. Do not assume that an environment has a realm literally named admin, internal, or customer.
Admin Panel Login
- Start the application with
make up-app. - Open
$LANA_ADMIN_BASE_URL(for example, http://admin.lana-bank.localhost:1355). - Log in as admin@galoy.io when redirected to Keycloak.
The admin panel uses the admin-panel client in main-internal with the OIDC Authorization Code Flow and PKCE. The local DEV authentication flows skip password validation; the master-console admin / admin credentials are separate.
Passwordless DEV flows are for local development only. Disable them with dev_auth_flows_enabled = false outside local development.
Obtain a Local Admin Token
From a development shell, after the backend has provisioned the admin user:
curl --fail-with-body -sS \
-d 'client_id=admin-panel' \
-d 'grant_type=password' \
-d 'username=admin@galoy.io' \
-d 'password=' \
"$LANA_KEYCLOAK_PUBLIC_URL/realms/main-internal/protocol/openid-connect/token"
Use the returned access_token as a Bearer token. This username-only direct grant is a development convenience, not the production integration flow.
Customer API Login
The bank does not ship an in-repo customer-facing web frontend. The customer API is available at $LANA_APP_BASE_URL/graphql for external clients such as lana-mobile-demo.
Customer clients authenticate against main-customer locally. The account must be provisioned and linked to its Lana party; a token from the admin realm is not interchangeable with a customer token. BATS uses the development direct-grant flow; see get_customer_access_token in bats/helpers.bash.
Authentication Flow
The Rust servers validate JWT signatures, expiry, audience, and the configured public issuer using realm JWKS. The admin and customer APIs also require a Keycloak sub. JWT authentication uses these UUID-valued Lana identity claims:
| API | Lana identity claim |
|---|---|
| Admin | userId |
| Customer | partyId |
| Partner | partnerUserId and partnerId |
A valid Keycloak token alone does not grant Lana access: the identity must exist and have the appropriate application permissions. Casbin authorization is enforced in the application layer. The partner API also accepts revocable partner API keys; see API Authentication.
Token Lifetimes
The shared realm configuration sets access tokens to 300 seconds (5 minutes) and the SSO session idle timeout to 86400 seconds (24 hours). Refresh-token rotation is enabled. Refresh/session behavior also depends on Keycloak's realm and client settings; there is no separate fixed 30-minute refresh-token lifetime guaranteed by this module.