Keycloak Configuration¶
This guide walks through setting up a Keycloak realm, client, user, roles, scopes, and mappers needed for TQPro authentication.
Two client configurations are documented:
- oauth2-proxy mode (legacy): Confidential client with client secret, used with oauth2-proxy
- Native OIDC mode (TQ-51): Public client with PKCE, used with oidc-client-ts in the frontend
Setup of other realms is similar.
🔧 1. Create Realm tqpro-adm¶
- Log in to Keycloak Admin Console
- From the top-left dropdown, click "Add Realm"
- Name it:
tqpro-adm - Click Create
🧩 2. Create Client tqweb-adm¶
- Go to Clients → Create
- Client ID:
tqweb-adm - Client Type:
OpenID Connect - Root URL:
https://tqadm-dev.vanevski.net - Click Save
Client Settings (oauth2-proxy mode):¶
- Access Type:
Confidential - Standard Flow Enabled: Yes
- Valid Redirect URIs:
- Web Origins:
- Post Logout Redirect URIs:
Credentials (oauth2-proxy mode):¶
- Go to the Credentials tab
- Copy the
Secretvalue — this goes intooauth2-proxyconfig
Client Settings (Native OIDC mode — TQ-51):¶
For native OIDC authentication where the frontend handles the OIDC flow directly:
- Access Type:
Public(no client secret) - Client Authentication: Off
- Standard Flow Enabled: Yes
- Proof Key for Code Exchange (PKCE):
S256 - Valid Redirect URIs:
- Web Origins:
- Post Logout Redirect URIs:
No client secret is needed since PKCE provides the security for public clients. Configure the auth-mode property in tlinqapi.properties to native-oidc or hybrid to enable JWT validation on the backend.
👤 3. Create User nvanevski¶
- Go to Users → Add User
- Username:
nvanevski - Email:
nvanevski@example.com - First Name:
Nikola - Last Name:
Vanevski - Email Verified: ✅ Yes
- Username:
- Click Create
Set Password¶
- Go to Users → nvanevski → Credentials
- Set password: e.g.,
changeme - Temporary: ❌ Off
- Click Set Password
- Set password: e.g.,
🎭 4. Create Roles agent and admin¶
- Go to Roles → Add Role
- Name:
agent
- Name:
- Repeat to add
admin
Assign Roles to User¶
- Go to Users → nvanevski → Role Mappings
- Select
agentandadminfrom Available Roles - Click Add Selected
- Select
📚 5. Create Client Scope audience-tqweb-adm¶
This ensures the access token contains aud: tqweb-adm
- Go to Client Scopes → Create
- Name:
audience-tqweb-adm - Protocol:
openid-connect
- Name:
- Click Save
Add Mapper¶
- Go to Client Scopes → audience-tqweb-adm → Mappers → Create
- Name:
audience-mapper - Mapper Type:
Audience - Included Client Audience:
tqweb-adm - Token Type:
Access token
- Name:
- Click Save
Assign Scope to Client¶
- Go to Clients → tqweb-adm → Client Scopes
- Under "Assigned Default Client Scopes", click Add
- Choose
audience-tqweb-adm - Click Add
🗺 6. Optional: Expose Roles in Token¶
If you want oauth2-proxy to access user roles via token:
Add a mapper to client:¶
- Go to Clients → tqweb-adm → Mappers → Create
- Name:
user-roles - Mapper Type:
User Realm Role - Token Claim Name:
roles - Claim JSON Type:
String - Multivalued: ✅
- Add to ID token: ✅
- Add to Access token: ✅
- Name:
🎨 7. Custom Login Theme¶
Keycloak's default login page can be branded to match TQPro. The approach inherits all default Keycloak FreeMarker templates and only overrides the CSS — no login.ftl changes needed for basic branding.
Directory Structure¶
config/keycloak-theme/tqpro/
login/
theme.properties
resources/
css/login.css
img/logo-full-horiz-1024.webp
Create the Theme¶
mkdir -p config/keycloak-theme/tqpro/login/resources/css
mkdir -p config/keycloak-theme/tqpro/login/resources/img
# Copy the company logo
cp tqweb-adm/adm/logo-full-horiz-1024.webp config/keycloak-theme/tqpro/login/resources/img/
theme.properties¶
At config/keycloak-theme/tqpro/login/theme.properties:
The parent=keycloak line inherits all default templates. Only the CSS is overridden.
login.css¶
At config/keycloak-theme/tqpro/login/resources/css/login.css:
/* TQPro / Perun Tours - Keycloak Login Theme */
/* Background */
body.kcBodyClass {
background: linear-gradient(135deg, #362c5d 0%, #2a2149 50%, #1a1533 100%) !important;
font-family: 'Inter', 'Noto Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
/* Hide the default Keycloak header/branding */
#kc-header-wrapper {
display: none !important;
}
/* Login card */
#kc-form-wrapper,
.card-pf {
border: none !important;
border-radius: 12px !important;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3) !important;
}
#kc-login {
max-width: 420px;
margin: 0 auto;
}
/* Logo - injected via background image on the header area */
#kc-logo-wrapper {
background: url('../img/logo-full-horiz-1024.webp') center center no-repeat !important;
background-size: contain !important;
height: 60px !important;
max-width: 280px;
margin: 0 auto 1.5rem auto;
}
#kc-logo-wrapper a {
visibility: hidden;
}
/* Form inputs */
#kc-form-login input[type="text"],
#kc-form-login input[type="password"] {
border-radius: 0.375rem;
border: 1px solid #dee2e6;
padding: 0.6rem 0.75rem;
font-size: 1rem;
}
#kc-form-login input[type="text"]:focus,
#kc-form-login input[type="password"]:focus {
box-shadow: 0 0 0 0.25rem rgba(54, 44, 93, 0.25);
border-color: #362c5d;
outline: none;
}
/* Login button */
#kc-login {
background: #362c5d !important;
border-color: #362c5d !important;
padding: 0.6rem !important;
font-weight: 600 !important;
border-radius: 0.375rem !important;
width: 100%;
}
#kc-login:hover {
background: #2a2149 !important;
border-color: #2a2149 !important;
}
/* Error messages */
.alert-error,
.kc-feedback-text {
color: #842029;
background-color: #f8d7da;
border-color: #f5c2c7;
border-radius: 0.375rem;
padding: 0.75rem 1rem;
}
/* Hide elements not needed */
#kc-info-wrapper,
#kc-registration {
display: none;
}
/* "Remember me" checkbox styling */
#kc-form-options label {
color: #6c757d;
font-size: 0.875rem;
}
/* Links */
a { color: #362c5d; }
a:hover { color: #2a2149; }
Deploy the Theme¶
Docker (volume mount in docker-compose.yaml):
Add to the keycloak service:
Docker (quick deploy without recomposing):
Bare-metal Keycloak:
Activate the Theme¶
- Open Keycloak Admin Console
- Go to Realm Settings → Themes tab
- Set Login theme to
tqpro - Click Save
No container restart is needed — the theme is picked up immediately.
Customizing HTML Structure¶
If CSS-only branding is not enough and you need to change the HTML layout, add a FreeMarker template override at config/keycloak-theme/tqpro/login/login.ftl. Since parent=keycloak is set, you only need to override the specific templates you want to change. Copy the original from the Keycloak source and modify it.
🔑 8. Realm Settings (Optional)¶
Set Session & Token Timeout¶
- Realm Settings → Tokens
- Access Token Lifespan: 5 minutes
- SSO Session Idle: 30 minutes
🌐 9. Test OAuth2 Flow¶
- Visit:
https://tqadm-dev.vanevski.net - Authenticate with
nvanevski - Inspect token using developer tools or
pass_access_token = true
You should see:
- "preferred_username": "nvanevski"
- "aud": "tqweb-adm"
- "roles": ["agent", "admin"]