Quick Start

Get a full CIAM stack running locally in under 5 minutes — PostgreSQL, Redis/Valkey, Kafka, OpenSearch, and the auth server.

Prerequisites: Docker Desktop (or Docker Engine + Compose v2), Java 21 JDK, Maven 3.9+
1

Clone the repository

Get the source code and navigate to the project root.

bash
git clone https://github.com/ciamplatform/ciam-auth.git
cd ciam-auth
2

Start infrastructure services

Docker Compose starts PostgreSQL, Redis/Valkey, Kafka, and OpenSearch.

bash
docker compose up -d

# Verify services are healthy
docker compose ps

NAME                 STATUS
ciam-postgres        running (healthy)
ciam-valkey          running (healthy)
ciam-kafka           running (healthy)
3

Build and run the auth server

Spring Boot with live reload. Flyway runs schema migrations automatically on startup.

bash
cd ciam-auth
mvn spring-boot:run

# Output (abbreviated)
...  Running Flyway migrations V1, V2, V3...
...  TenantContextFilter registered
...  Started CiamAuthApplication on port 8080
4

Verify the discovery endpoint

The OIDC discovery document confirms the server is running correctly.

bash
curl http://localhost:8080/.well-known/openid-configuration | jq .

{
  "issuer": "http://localhost:8080",
  "authorization_endpoint": "http://localhost:8080/oauth2/authorize",
  "token_endpoint": "http://localhost:8080/oauth2/token",
  "jwks_uri": "http://localhost:8080/oauth2/jwks",
  "userinfo_endpoint": "http://localhost:8080/userinfo"
}

Configuration

Key settings in ciam-auth/src/main/resources/application.yml:

application.yml
ciam:
  platform:
    domain: auth.platform.com
  tenant:
    default-slug: dev
    strict-mode: false    # set true in production

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/ciam_auth
    hikari.maximum-pool-size: 20
  data.redis.host: localhost
  kafka.bootstrap-servers: localhost:9092

Your First Tenant

Create a tenant — cURL
curl -X POST http://localhost:8080/admin/tenants \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <admin-token>" \
  -d '{
    "name": "Acme Corp",
    "slug": "acme",
    "mfaRequired": false
  }'

Authorization Code + PKCE

The recommended flow for web and mobile applications. PKCE protects against authorization code interception attacks.

JavaScript — PKCE flow
// 1. Generate code verifier + challenge
const verifier  = generateRandomString(64)
const challenge = await sha256base64url(verifier)

// 2. Redirect to authorization endpoint
const params = new URLSearchParams({
  response_type: 'code', client_id: 'your-client-id',
  redirect_uri: 'https://app.example.com/callback',
  scope: 'openid profile email',
  code_challenge: challenge, code_challenge_method: 'S256'
})
window.location.href = `https://acme.auth.platform.com/oauth2/authorize?${params}`

// 3. Exchange code for tokens at callback
const resp = await fetch('https://acme.auth.platform.com/oauth2/token', {
  method: 'POST',
  body: new URLSearchParams({
    grant_type: 'authorization_code', code: authCode,
    client_id: 'your-client-id', code_verifier: verifier
  })
})

Token Validation

Java — Spring Security resource server
// application.yml
spring.security.oauth2.resourceserver.jwt:
  jwk-set-uri: https://acme.auth.platform.com/oauth2/jwks
  issuer-uri:  https://acme.auth.platform.com

// SecurityConfig.java
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
  http
    .authorizeHttpRequests(auth -> auth
      .requestMatchers("/public/**").permitAll()
      .anyRequest().authenticated())
    .oauth2ResourceServer(o -> o.jwt(Customizer.withDefaults()));
  return http.build();
}

API Reference

All admin endpoints require a Bearer token with admin role. Base URL: https://{tenant}.auth.platform.com/admin

Tenant API

GET/admin/tenantsList all tenants
POST/admin/tenantsCreate a tenant
PUT/admin/tenants/{id}Update tenant

User API

GET/admin/usersList users (paginated)
POST/admin/usersCreate user
PUT/admin/users/{id}Update user
DELETE/admin/users/{id}Delete user
POST/admin/invitationsInvite user by email

OAuth2 Client API

GET/admin/oauth2-clientsList OAuth2 clients
POST/admin/oauth2-clientsRegister OAuth2 client
DELETE/admin/oauth2-clients/{id}Revoke client

MFA API

GET/admin/mfa-enrollmentsList MFA enrollments
DELETE/admin/mfa-enrollments/{id}Remove enrollment

Guide: Enabling MFA

Enable MFA for a tenant
curl -X PUT https://acme.auth.platform.com/admin/tenants/ten_01HX \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{ "mfaRequired": true }'

Guide: Kafka Auth Events

Sample auth event — JSON
{
  "eventType":  "LOGIN_SUCCESS",
  "tenantId":   "acme",
  "userId":     "user_01HX...",
  "mfaMethod":  "TOTP",
  "timestamp":  "2026-04-14T09:31:00Z"
}

Event types: LOGIN_SUCCESS, LOGIN_FAILURE, MFA_CHALLENGED, MFA_SUCCESS, ACCOUNT_LOCKED, USER_CREATED.

Need help? Open a GitHub issue or join the community Slack.
Explore all features →