WordPress
WordPress Integration Guide
This comprehensive guide walks you through integrating WordPress with Keycloak for single sign-on (SSO) authentication. WordPress offers multiple plugin options for OAuth/OpenID Connect integration, each with different strengths and use cases.
Overview
WordPress Keycloak integration enables:
- Single Sign-On (SSO) - Users authenticate once across all systems
- Centralized User Management - Manage users in Keycloak, not WordPress
- Role-Based Access Control - Map Keycloak roles to WordPress roles
- Enhanced Security - Leverage Keycloak’s advanced security features
- Unified User Experience - Seamless authentication across applications
Plugin Options
1. miniOrange OAuth Single Sign On (Recommended for Enterprise)
Best for: Enterprise environments requiring comprehensive features and professional support.
Key Features:
- ✅ Native Keycloak support with pre-configured templates
- ✅ Advanced role-based access control (RBAC)
- ✅ 24/7 professional support
- ✅ Unlimited users in free version
- ✅ Multiple identity providers support
Installation:
# Via WordPress Admin
# 1. Go to Plugins > Add New
# 2. Search for "OAuth Single Sign On – SSO (OAuth Client)"
# 3. Install and activate
# Via WP-CLI
wp plugin install miniorange-login-with-eve-online-google-facebook --activate2. OpenID Connect Generic Client (Recommended for Developers)
Best for: Developers who want a lightweight, free solution with full control.
Key Features:
- ✅ Completely free with no premium limitations
- ✅ Clean, minimalist implementation
- ✅ Active open-source development
- ✅ Developer-friendly with customization hooks
- ✅ Reliable and battle-tested
Installation:
# Via WordPress Admin
# 1. Go to Plugins > Add New
# 2. Search for "OpenID Connect Generic Client"
# 3. Install and activate
# Via WP-CLI
wp plugin install openid-connect-generic --activate3. WP OAuth Server (For Complex Architectures)
Best for: Complex multi-system architectures where WordPress needs to act as an identity provider.
Key Features:
- ✅ WordPress as OAuth provider
- ✅ Bidirectional authentication with Keycloak
- ✅ Federation scenarios
- ✅ Advanced integration patterns
Quick Start
Step 1: Create Application in Skycloak
- In Skycloak, navigate to your cluster → Applications
- Click Create Application and configure:
-
Name:
wordpress-sso(or your preferred name) - Type: Confidential
- Grant Types: Authorization Code + Refresh Token
- Redirect URIs: You’ll add these in Step 2 after configuring your WordPress plugin
-
Name:
- After creation, copy the Client ID and Client Secret — you’ll need these for WordPress
Step 2: Configure WordPress Plugin
Choose your plugin and follow the specific configuration:
miniOrange Configuration:
- Go to Settings → miniOrange OAuth → Configure OAuth
- Select “Keycloak” from the application dropdown
- Enter your configuration:
- Client ID: Your Keycloak client ID
- Client Secret: From Keycloak credentials tab
-
Scope:
openid email profile roles
- Configure endpoints (auto-populated for Keycloak)
- Set up attribute mapping:
-
Username:
preferred_username -
Email:
email -
First Name:
given_name -
Last Name:
family_name
-
Username:
- Configure role mapping in the Role Mapping tab
Redirect URI for Keycloak:
https://your-site.com/wp-content/plugins/miniorange-login-with-eve-online-google-facebook/mo_oauth_callback.php
Add this URL to your application’s Redirect URIs in Skycloak’s Applications page.
OpenID Connect Generic Configuration:
- Go to Settings → OpenID Connect Generic
- Enter your configuration:
- Client ID: Your Keycloak client ID
- Client Secret: From Keycloak credentials tab
-
OpenID Scope:
openid email profile
- Configure endpoints:
-
Login Endpoint:
https://your-keycloak/realms/your-realm/protocol/openid-connect/auth -
Userinfo Endpoint:
https://your-keycloak/realms/your-realm/protocol/openid-connect/userinfo -
Token Endpoint:
https://your-keycloak/realms/your-realm/protocol/openid-connect/token -
End Session Endpoint:
https://your-keycloak/realms/your-realm/protocol/openid-connect/logout
-
Login Endpoint:
Redirect URIs — Add to Skycloak:
The OpenID Connect Generic plugin uses two possible callback URLs. Add both to your application’s Redirect URIs in Skycloak to avoid invalid_redirect_uri errors:
| URI | When it’s used |
|---|---|
https://your-site.com/wp-admin/admin-ajax.php?action=openid-connect-authorize |
Default — used unless you enable the alternate |
https://your-site.com/openid-connect-authorize |
Alternate — only used if you check “Alternate Redirect URI” in the plugin settings |
Important: Add both URIs to be safe. If you only add one, make sure it matches the mode your plugin is using. The most common mistake is adding only the alternate URI while the plugin is still using the default.
Production Configuration:
For production environments, use constants in wp-config.php:
// OpenID Connect Generic Plugin
define('OPENID_CONNECT_CLIENT_ID', 'your-client-id');
define('OPENID_CONNECT_CLIENT_SECRET', 'your-client-secret');
define('OPENID_CONNECT_SCOPE', 'openid email profile');
define('OPENID_CONNECT_LOGIN_ENDPOINT_URL', 'https://keycloak/realms/realm/protocol/openid-connect/auth');
define('OPENID_CONNECT_USERINFO_ENDPOINT_URL', 'https://keycloak/realms/realm/protocol/openid-connect/userinfo');
define('OPENID_CONNECT_TOKEN_VALIDATION_ENDPOINT_URL', 'https://keycloak/realms/realm/protocol/openid-connect/token');
define('OPENID_CONNECT_END_SESSION_ENDPOINT_URL', 'https://keycloak/realms/realm/protocol/openid-connect/logout');
// Security hardening
define('FORCE_SSL_ADMIN', true);
define('FORCE_SSL_LOGIN', true);Step 3: Test Integration
- Logout from WordPress completely
- Clear browser cache and cookies
- Navigate to your WordPress login page
- Click the SSO login button
- Authenticate in Keycloak
- Verify you’re redirected back and logged into WordPress
Role Mapping
Keycloak Configuration
Create role mappers in your Keycloak client:
- Go to Clients → Your Client → Mappers → Create
- Configure the mapper:
-
Name:
wordpress-roles -
Mapper Type:
User Realm Role -
Token Claim Name:
roles - Add to ID token: ON
- Add to access token: ON
-
Name:
WordPress Role Mapping
miniOrange Plugin:
Role mapping is handled through the plugin’s UI:
- Go to Settings → miniOrange OAuth → Role Mapping
- Map Keycloak roles to WordPress roles:
-
admin→Administrator -
editor→Editor -
author→Author -
user→Subscriber
-
OpenID Connect Generic:
Add this code to your theme’s functions.php:
add_action('openid-connect-generic-update-user-using-current-claim', function($user, $user_claim) {
if (!empty($user_claim['realm_access']['roles'])) {
$roles = $user_claim['realm_access']['roles'];
if (in_array('wordpress-admin', $roles)) {
$user->set_role('administrator');
} elseif (in_array('wordpress-editor', $roles)) {
$user->set_role('editor');
} elseif (in_array('wordpress-author', $roles)) {
$user->set_role('author');
} elseif (in_array('wordpress-contributor', $roles)) {
$user->set_role('contributor');
} else {
$user->set_role('subscriber');
}
}
}, 10, 2);Login Experience
Automatic Integration
Both plugins automatically add SSO login buttons to the WordPress login page. No additional configuration is needed.
Custom Login Buttons
Shortcode Integration:
Add SSO login to any page or post:
<!-- OpenID Connect Generic -->
[openid_connect_generic_login_button]
<!-- miniOrange (use plugin's shortcode generator) -->
[miniorange_sso_login]PHP Integration:
Add to your theme templates:
<?php if (function_exists('openid_connect_generic_login_button')): ?>
<div class="sso-login">
<h3>Login with SSO</h3>
<?php echo openid_connect_generic_login_button(); ?>
</div>
<?php endif; ?>
Direct URL:
Create custom login links:
<a href="/wp-admin/admin-ajax.php?action=openid-connect-authorize" class="sso-login-btn">
Login with Keycloak
</a>Custom Styling
Style your SSO login buttons:
.openid-connect-login-button {
background-color: #007cba;
color: white;
padding: 10px 20px;
text-decoration: none;
border-radius: 5px;
display: inline-block;
margin: 10px 0;
font-weight: bold;
}
.openid-connect-login-button:hover {
background-color: #005a87;
color: white;
}Security Best Practices
SSL/TLS Configuration
// Add to wp-config.php
define('FORCE_SSL_ADMIN', true);
define('FORCE_SSL_LOGIN', true);
// Enable HSTS (in .htaccess or server config)
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"Secure Credential Storage
// Use environment variables
define('OPENID_CONNECT_CLIENT_SECRET', $_ENV['KEYCLOAK_CLIENT_SECRET']);
// Or use wp-config.php constants (not database)
define('OPENID_CONNECT_CLIENT_SECRET', 'your-secret-here');Optional: Disable WordPress Login
// Force SSO-only authentication
add_filter('wp_authenticate_user', function($user) {
if (!is_wp_error($user) && !current_user_can('manage_options')) {
return new WP_Error('sso_only', 'Please use SSO to login');
}
return $user;
}, 10, 1);Token Security
- Use short access token lifetimes (15-30 minutes)
- Implement refresh token rotation in Keycloak
- Enable token validation and signature verification
- Monitor for suspicious authentication patterns
Troubleshooting
Common Issues
“Invalid Client” Error:
- ✅ Verify client ID and secret are correct
- ✅ Check client authentication is enabled in Keycloak
- ✅ Ensure no extra spaces in credentials
- ✅ Verify client exists in the correct realm
- ✅ Check client is not disabled
Debug Steps:
# Test client credentials
curl -X POST \
https://your-keycloak/realms/your-realm/protocol/openid-connect/token \
-d "grant_type=client_credentials" \
-d "client_id=your-client-id" \
-d "client_secret=your-client-secret"Redirect URI Mismatch:
- ✅ Copy exact callback URL from WordPress plugin settings
- ✅ Add it to Keycloak’s Valid Redirect URIs
- ✅ Check for HTTP vs HTTPS mismatches
- ✅ Verify URL path is exactly correct
- ✅ Include both callback and logout URLs
Common Callback URLs:
# miniOrange
https://your-site.com/wp-content/plugins/miniorange-login-with-eve-online-google-facebook/mo_oauth_callback.php
# OpenID Connect Generic
https://your-site.com/wp-admin/admin-ajax.php?action=openid-connect-authorize
https://your-site.com/openid-connect-authorize
Most common cause: Adding only one redirect URI when the plugin expects another. For the OpenID Connect Generic plugin, the default callback URL includes query parameters (?action=openid-connect-authorize). If you enabled “Alternate Redirect URI” in the plugin but didn’t update your Skycloak redirect URIs (or vice versa), the URLs won’t match.
Quick fix: Add both redirect URIs to your application in Skycloak:
https://your-site.com/wp-admin/admin-ajax.php?action=openid-connect-authorize
https://your-site.com/openid-connect-authorize
SSL Certificate Issues:
- ✅ Ensure complete certificate chain is installed
- ✅ Check WordPress can reach Keycloak HTTPS endpoints
- ✅ Verify system time synchronization
- ✅ Test certificate validity
Debug Commands:
# Test SSL connection
openssl s_client -connect your-keycloak:443 -servername your-keycloak
# Check certificate
curl -I https://your-keycloak/auth/realms/your-realm/.well-known/openid-configuration
# Test from WordPress server
wp eval "echo file_get_contents('https://your-keycloak/auth/realms/your-realm/.well-known/openid-configuration');"Missing User Attributes:
- ✅ Verify required scopes are configured (openid, email, profile)
- ✅ Check Keycloak user has all attributes populated
- ✅ Review attribute mappings in both systems
- ✅ Test with token introspection
Attribute Mapping:
Keycloak → WordPress
preferred_username → user_login
email → user_email
given_name → first_name
family_name → last_name
name → display_name
Debug Logging
Enable debug logging to troubleshoot issues:
// Add to wp-config.php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
// For OpenID Connect Generic plugin
define('OPENID_CONNECT_GENERIC_LOG', true);Check logs at /wp-content/debug.log for detailed error information.
Production Deployment
Pre-Deployment Checklist
Security Review:
- ✅ All credentials stored securely (not in database)
- ✅ SSL/TLS properly configured
- ✅ Role mappings audited and tested
- ✅ Redirect URIs restricted to necessary paths
- ✅ Security headers enabled
- ✅ WordPress and plugins updated
- ✅ Monitoring and alerting configured
// Security hardening checklist
define('FORCE_SSL_ADMIN', true);
define('FORCE_SSL_LOGIN', true);
define('DISALLOW_FILE_EDIT', true);
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);
define('WP_DEBUG_DISPLAY', false);Performance Optimization:
- ✅ Caching configured (Redis/Memcached)
- ✅ Database queries optimized
- ✅ CDN configured for static assets
- ✅ Session storage optimized
- ✅ Token lifetimes configured appropriately
// Performance settings
define('WP_CACHE', true);
define('WP_REDIS_HOST', 'localhost');
define('WP_REDIS_PORT', 6379);
// Session configuration
ini_set('session.gc_maxlifetime', 1800); // 30 minutes
Backup Strategy:
- ✅ WordPress files and database backed up
- ✅ Configuration files backed up
- ✅ Keycloak realm configuration exported
- ✅ Rollback procedures documented
- ✅ Emergency access plan created
# Backup WordPress
wp db export backup.sql
tar -czf wp-backup.tar.gz wp-content/
# Backup Keycloak realm
./kcadm.sh get realms/your-realm > realm-backup.jsonTesting Checklist:
- ✅ SSO login works for all user types
- ✅ Role mapping functions correctly
- ✅ User attributes sync properly
- ✅ Logout works (single logout)
- ✅ Error handling works correctly
- ✅ Performance under load tested
# Load testing
ab -n 1000 -c 10 https://your-site.com/wp-login.php
# Security testing
nmap -sS -sV your-site.comAdvanced Configuration
Multi-site WordPress
For WordPress multisite installations:
// Network-wide SSO configuration
define('OPENID_CONNECT_GENERIC_SETTINGS', serialize([
'client_id' => 'your-client-id',
'client_secret' => 'your-client-secret',
'scope' => 'openid email profile',
// ... other settings
]));
// Per-site role mapping
add_filter('openid_connect_generic_user_creation', function($user_data, $claims) {
$site_id = get_current_blog_id();
// Site-specific role mapping logic
switch ($site_id) {
case 1:
$user_data['role'] = 'administrator';
break;
case 2:
$user_data['role'] = 'editor';
break;
default:
$user_data['role'] = 'subscriber';
}
return $user_data;
}, 10, 2);WooCommerce Integration
For WooCommerce stores:
// Map Keycloak roles to WooCommerce roles
add_action('openid-connect-generic-update-user-using-current-claim', function($user, $user_claim) {
if (!empty($user_claim['roles'])) {
$roles = $user_claim['roles'];
if (in_array('shop-manager', $roles)) {
$user->set_role('shop_manager');
} elseif (in_array('customer', $roles)) {
$user->set_role('customer');
}
}
}, 10, 2);
// Sync customer data
add_action('openid-connect-generic-update-user-using-current-claim', function($user, $user_claim) {
if (!empty($user_claim['billing_address'])) {
update_user_meta($user->ID, 'billing_address_1', $user_claim['billing_address']['street']);
update_user_meta($user->ID, 'billing_city', $user_claim['billing_address']['city']);
// ... other billing fields
}
}, 10, 2);Support and Resources
Documentation
- WordPress Plugin Development
- OpenID Connect Specification
- Keycloak Documentation
- OpenID Connect Generic Plugin GitHub
Professional Support
For enterprise deployments, consider:
- WordPress VIP support
- Keycloak Red Hat support
- miniOrange enterprise support
- Custom development services
- Email Skycloak support at [email protected]
Conclusion
WordPress Keycloak integration provides a robust foundation for centralized authentication and user management. Choose the plugin that best fits your needs:
- miniOrange for enterprise features and support
- OpenID Connect Generic for developer flexibility and control
- WP OAuth Server for complex federation scenarios
Follow the security best practices and testing procedures outlined in this guide to ensure a successful production deployment.