Skip to main content

Auth Service — Local Dev Setup

Status: populated Owner: Engineering Last updated: 2026-04-18

1. compose

docker compose up postgres redis vault keycloak. Vault runs in dev mode with root-token=devroot. Keycloak runs with realm ghasi-local pre-imported (see infra/docker/keycloak/realm-ghasi-local.json) containing a test client auth-service and two users: admin@example.com, user@example.com.

2. Env

PORT=3020
DATABASE_URL=postgresql://auth:auth@localhost:5432/ghasi_sms?schema=auth
REDIS_URL=redis://localhost:6379/2
VAULT_ADDR=http://localhost:8200
VAULT_TOKEN=devroot

# Base IdP — Keycloak (default)
KEYCLOAK_BASE_URL=http://localhost:8080
KEYCLOAK_REALM=ghasi-local
KEYCLOAK_CLIENT_ID=auth-service
KEYCLOAK_CLIENT_SECRET=dev-secret
KEYCLOAK_ADMIN_USER=admin
KEYCLOAK_ADMIN_PASSWORD=admin

# Legacy provider — Firebase (optional; only if FIREBASE_LEGACY_ENABLED=true)
FIREBASE_LEGACY_ENABLED=false
# FIREBASE_PROJECT_ID=ghasi-dev
# FIREBASE_CREDENTIALS=/secrets/fb-dev.json

NATS_URL=nats://localhost:4222
ACCESS_TOKEN_TTL=15m
REFRESH_TOKEN_TTL=30d
JWKS_ROTATION_CRON=0 0 1 * *
LOG_LEVEL=debug

3. Commands

pnpm install
pnpm --filter @ghasi/service-auth prisma migrate dev
pnpm --filter @ghasi/service-auth prisma db seed # seeds 1 account + admin user + test API key
pnpm --filter @ghasi/service-auth dev

4. Smoke test

# Native fallback login (test account only)
curl -X POST http://localhost:3020/v1/auth/login -H "Content-Type: application/json" \
-d '{"email":"admin@example.com","password":"ChangeMe!1"}'

# Keycloak SSO (default path) — browser flow; CLI equivalent:
curl -v "http://localhost:3020/v1/auth/sso/start?tenant=local"

# JWKS (consumed by Kong)
curl http://localhost:3020/.well-known/jwks.json

# Keycloak admin sanity
curl http://localhost:8080/realms/ghasi-local/.well-known/openid-configuration

5. Seed data

  • 1 tenant (local), 1 account, 1 admin user mirrored between Postgres (auth.users) and Keycloak realm ghasi-local.
  • 1 API key for Kong smoke (printed once).
  • 2 JWK keys (active + next).
  • Default tenant_identity_providers row: providerId=keycloak, kind=oidc, is_default=true.

6. Simulating a tenant external IdP (OIDC)

docker compose up mock-oidc starts a second Keycloak instance at http://localhost:9080 that represents a customer's IdP ("acme-corp"). Register it against the main Keycloak as a brokered IdP:

pnpm --filter @ghasi/service-auth tenant:register-oidc \
--tenant=local --providerId=tenant-oidc:acme \
--discoveryUrl=http://localhost:9080/realms/acme/.well-known/openid-configuration

Then visit http://localhost:3020/v1/auth/sso/start?tenant=local&provider=tenant-oidc:acme to exercise the full brokered flow end-to-end.