Appearance
Keycloak Realm Setup
Gatez uses Keycloak as the identity provider for both portals. The gateway realm is auto-imported on first start from config/keycloak/gateway-realm.json.
Auto-Provisioned Resources
On docker compose up, Keycloak imports:
| Resource | Name | Purpose |
|---|---|---|
| Realm | gateway | Main realm for all Gatez users |
| Client | operator-portal | Public OIDC client for the operator portal (PKCE, no secret) |
| Client | developer-portal | Public OIDC client for the developer portal (PKCE, no secret) |
Client Configuration
Both portal clients use:
- Protocol: OpenID Connect
- Access Type: Public (no client secret — uses PKCE S256)
- Standard Flow: Enabled (authorization code flow)
- Direct Access Grants: Enabled (for testing with curl)
- Valid Redirect URIs:
https://operator.gatez.dev/*/https://developer.gatez.dev/*(andhttp://localhost:3003/*/http://localhost:3004/*for dev) - Web Origins:
+(allows all origins matching redirect URIs)
Creating Demo Users
Via Admin API
bash
# Get admin token
KC_PASS="your-keycloak-admin-password"
TOKEN=$(curl -s -X POST "http://localhost:8081/realms/master/protocol/openid-connect/token" \
-d "client_id=admin-cli" -d "username=admin" -d "password=$KC_PASS" \
-d "grant_type=password" | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
# Create operator user (platform admin)
curl -X POST "http://localhost:8081/admin/realms/gateway/users" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"username": "sarah.platform",
"email": "sarah@company.com",
"firstName": "Sarah",
"lastName": "Chen",
"enabled": true,
"emailVerified": true,
"credentials": [{"type": "password", "value": "demo123", "temporary": false}],
"attributes": {"tenant_id": [""]}
}'
# Create developer user (tenant user)
curl -X POST "http://localhost:8081/admin/realms/gateway/users" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"username": "raj.developer",
"email": "raj@company.com",
"firstName": "Raj",
"lastName": "Patel",
"enabled": true,
"emailVerified": true,
"credentials": [{"type": "password", "value": "demo123", "temporary": false}],
"attributes": {"tenant_id": ["retail"]}
}'Via Admin Console
- Navigate to
https://keycloak.yourdomain.com(orhttp://localhost:8081) - Login with admin credentials
- Select the
gatewayrealm - Go to Users -> Add user
- Set username, email, first/last name
- Under Credentials, set a password (toggle "Temporary" off)
- Under Attributes, add
tenant_idwith the tenant identifier
Role Mapping
Gatez uses JWT claims for authorization:
| Claim | Source | Used By |
|---|---|---|
preferred_username | Keycloak user profile | Display name in portals |
email | Keycloak user profile | User identification |
realm_access.roles | Realm roles | Authorization (platform-admin, tenant-admin, tenant-user) |
tenant_id | User attribute | Multi-tenant scoping |
Key Roles
| Role | Portal | Capabilities |
|---|---|---|
platform-admin | Operator | Full access to all tenants, routes, analytics, settings |
tenant-admin | Both | Manage users, keys, and settings for their tenant |
tenant-user | Developer | View APIs, request keys, view own usage |
SAML / SSO Brokering
For enterprise customers using their own IdP (Okta, Azure AD, etc.):
- Configure via API:
PUT /api/tenants/:id/saml-configwith IdP metadata URL - Keycloak brokering: Gatez stores the SAML config and provides Keycloak brokering instructions
- The operator portal has a SAML tab in the tenant drawer for configuration
See the SSO documentation for MCP_OAUTH_* variables.
Production Checklist
- [ ] Change
KEYCLOAK_ADMIN_PASSWORDfrom default - [ ] Configure Valid Redirect URIs to match your domain (not localhost)
- [ ] Enable HTTPS (Keycloak behind Caddy with auto-TLS)
- [ ] Create real users (not demo accounts)
- [ ] Set up realm email for password reset flows
- [ ] Configure session timeouts appropriate for your security policy