Appearance
Keycloak Realms
Microtec uses two Keycloak realms to isolate authentication contexts for different user populations. Each realm has distinct client configurations, identity providers, and token policies.
Realm Overview
| Realm | Name | Users | Domain |
|---|---|---|---|
| ERP | microtec | Tenant employees using the ERP system | auth.{env-domain}/realms/microtec |
| Business Owner | businessowner | Tenant administrators and business owners | auth.{env-domain}/realms/businessowner |
microtec Realm (ERP)
Purpose
The microtec realm authenticates all regular ERP users: accountants, inventory managers, HR staff, and other employees who use day-to-day ERP functionality. It is multi-tenant aware — each user belongs to a tenant group that scopes their data access.
Clients
| Client ID | Type | Usage |
|---|---|---|
erp-home | Public (SPA) | ERP home and navigation shell (port 4401) |
apps-accounting | Public (SPA) | Accounting module (port 4402) |
apps-hr | Public (SPA) | HR module (port 4403) |
apps-finance | Public (SPA) | Finance module (port 4404) |
apps-sales | Public (SPA) | Sales module (port 4405) |
apps-purchase | Public (SPA) | Purchase module (port 4406) |
apps-inventory | Public (SPA) | Inventory module (port 4407) |
app-distribution | Public (SPA) | Distribution module (port 4408) |
fixed-assets | Public (SPA) | Fixed Assets module (port 4409) |
erp-backend | Confidential | Backend services (JWT introspection) |
zap-scanner | Service account | OWASP ZAP authenticated scans (stage only) |
Client Configuration (SPA Clients)
All Angular SPA clients share the same configuration pattern:
json
{
"clientId": "apps-accounting",
"protocol": "openid-connect",
"publicClient": true,
"standardFlowEnabled": true,
"implicitFlowEnabled": false,
"directAccessGrantsEnabled": false,
"pkceCodeChallengeMethod": "S256",
"redirectUris": [
"https://erp.microtecstage.com/*",
"http://localhost:4402/*"
],
"webOrigins": [
"https://erp.microtecstage.com",
"http://localhost:4402"
],
"attributes": {
"backchannel.logout.url": "https://gateway.microtecstage.com/logout/backchannel",
"backchannel.logout.session.required": "true"
}
}PKCE Required
All SPA clients use PKCE (S256) with the Authorization Code flow. Implicit flow is disabled. This prevents token leakage via the URL fragment and is required by current OAuth 2.0 security best practices.
Token Configuration
| Setting | Value |
|---|---|
| Access token lifetime | 15 minutes |
| Refresh token lifetime | 8 hours (aligned with working day) |
| SSO session max | 8 hours |
| Offline access | Disabled |
| Token signing algorithm | RS256 |
Claims in microtec Tokens
The erp-policy-mapper SPI (custom Keycloak extension) adds the following claims to tokens:
json
{
"sub": "keycloak-user-uuid",
"iss": "https://auth.microtecstage.com/realms/microtec",
"aud": "apps-accounting",
"exp": 1705312800,
"preferred_username": "ahmed.ali",
"email": "ahmed.ali@acmecorp.com",
"given_name": "Ahmed",
"family_name": "Ali",
"tenant_id": "ACME_Corp",
"roles": ["Accountant", "AccountingManager"],
"permissions": ["Accounting.Read", "Accounting.Write", "Accounting.Approve"]
}See RBAC Policies for how roles maps to permissions.
businessowner Realm
Purpose
The businessowner realm authenticates tenant administrators and business owners who manage subscriptions, configure tenant settings, onboard users, and access cross-tenant administrative functions via the Business Owner portal.
Clients
| Client ID | Type | Usage |
|---|---|---|
bussiness-owners | Public (SPA) | BO Portal Angular app (port 4301) |
bo-backend | Confidential | BO backend services |
account | Built-in Keycloak | Account management console (DISABLED — see note) |
account-console Client Is Disabled
The Keycloak built-in account-console client is disabled in both realms. Users cannot self-manage their Keycloak account via the Keycloak UI. Account management (password reset, profile updates) is handled through the Microtec BO portal using the Keycloak Admin REST API, not the Keycloak account console.
This is intentional — the account console exposes Keycloak internals to end users and was disabled during realm provisioning (see ConfigureRealmClients step in the Keycloak provisioning automation).
Token Configuration
| Setting | Value |
|---|---|
| Access token lifetime | 30 minutes (BO sessions are longer-lived) |
| Refresh token lifetime | 24 hours |
| SSO session max | 24 hours |
| MFA | Optional (configurable per tenant) |
Claims in businessowner Tokens
json
{
"sub": "keycloak-user-uuid",
"iss": "https://auth.microtecstage.com/realms/businessowner",
"preferred_username": "owner@acmecorp.com",
"tenant_id": "ACME_Corp",
"roles": ["TenantOwner"],
"managed_tenants": ["ACME_Corp", "ACME_Branch"]
}Identity Providers
Both realms support external IdP federation for enterprise SSO:
| IdP | Realm | Flow |
|---|---|---|
| Microsoft Entra ID (Azure AD) | Both | OIDC federation |
| Google Workspace | microtec | OIDC federation |
| SAML 2.0 Enterprise | microtec | SAML IdP (per-tenant config) |
Authentication flow priority (configured in erp-policy-mapper SPI):
| Flow | Priority | Trigger |
|---|---|---|
| MAC address flow | 10 | Corporate device on internal network |
| Cookie/session flow | 20 | Existing Keycloak session |
| IdP redirect flow | 30 | External IdP configured for user's email domain |
| Username/password | 40 (fallback) | Default |
Realm Provisioning
Realms are provisioned automatically via the Keycloak Provisioning Automation (see KeycloakProviders/). The provisioning sequence:
- Create realm with token lifetimes and security policies
- Create and configure all clients (disable
account-console, enableaccount) - Import client scopes and protocol mappers
- Configure authentication flows with correct priorities
- Register
erp-policy-mapperSPI for permission claim injection - Set up identity providers (if configured for the environment)
Backchannel Logout
Backchannel logout is configured on all SPA clients and verified in the provisioning code. When a user logs out from any ERP app, Keycloak sends a backchannel logout request to https://gateway.{domain}/logout/backchannel. The Gateway service broadcasts this to all internal services to invalidate session caches. This prevents stale sessions persisting in Redis after logout.