Strapi Keycloak Passport
Seamlessly integrate Keycloak authentication with Strapi Admin Panel.
Strapi Keycloak Passport Plugin
Enterprise-grade Keycloak authentication for Strapi v5 Admin Panel with full RBAC support.
Features
- Single Sign-On (SSO) - Replace Strapi's default admin login with Keycloak OAuth2
- Keycloak 17+ Support - Works with both modern (17+) and legacy Keycloak versions
- Role Mapping - Dynamically map Keycloak roles to Strapi admin roles via UI
- Token Caching - Intelligent caching with automatic refresh before expiry
- Audit Logging - Comprehensive audit trail for all authentication events
- Strapi RBAC Integration - Leverages Strapi's native Roles & Permissions
- Secure by Default - Error sanitization, HttpOnly cookies, input validation
Requirements
- Node.js >= 20.0.0
- Strapi v5.x
- Keycloak 17+ (or legacy with configuration flag)
Installation
yarn add strapi-keycloak-passportor
npm install strapi-keycloak-passportConfiguration
Plugin Configuration
Add to your config/plugins.js (or config/plugins.ts):
module.exports = ({ env }) => ({
'strapi-keycloak-passport': {
enabled: env.bool('KEYCLOAK_ENABLED', true),
config: {
// Required: Keycloak server URL (without trailing slash)
KEYCLOAK_AUTH_URL: env('KEYCLOAK_AUTH_URL', 'https://keycloak.example.com'),
// Required: Keycloak realm name
KEYCLOAK_REALM: env('KEYCLOAK_REALM', 'master'),
// Required: OAuth client credentials
KEYCLOAK_CLIENT_ID: env('KEYCLOAK_CLIENT_ID', 'strapi-admin'),
KEYCLOAK_CLIENT_SECRET: env('KEYCLOAK_CLIENT_SECRET'),
// Optional: Set to true for Keycloak versions < 17 (uses /auth prefix)
KEYCLOAK_LEGACY_MODE: env.bool('KEYCLOAK_LEGACY_MODE', false),
// Optional: Role configuration
roleConfigs: {
// Default Strapi role ID when no mapping exists
defaultRoleId: env.int('KEYCLOAK_DEFAULT_ROLE_ID', 1),
// Keycloak roles to exclude from the mapping UI
excludedRoles: [
'uma_authorization',
'offline_access',
'default-roles-master',
],
},
},
},
});Environment Variables
# Required
KEYCLOAK_AUTH_URL=https://keycloak.example.com
KEYCLOAK_REALM=master
KEYCLOAK_CLIENT_ID=strapi-admin
KEYCLOAK_CLIENT_SECRET=your-client-secret
# Optional
KEYCLOAK_ENABLED=true
KEYCLOAK_LEGACY_MODE=false
KEYCLOAK_DEFAULT_ROLE_ID=1Keycloak Version Compatibility
| Keycloak Version | KEYCLOAK_LEGACY_MODE | URL Format |
|---|---|---|
| 17+ (Quarkus) | false (default) | https://keycloak.example.com/realms/{realm}/... |
| < 17 (WildFly) | true | https://keycloak.example.com/auth/realms/{realm}/... |
Keycloak Setup
1. Create an OAuth Client
- Navigate to Keycloak Admin Console → Clients
- Click Create Client:
- Client ID:
strapi-admin - Client Protocol:
openid-connect - Client Authentication:
On(Confidential)
- Client ID:
- Configure settings:
- Root URL:
https://your-strapi-instance.com - Valid Redirect URIs:
https://your-strapi-instance.com/admin/* - Web Origins:
https://your-strapi-instance.com
- Root URL:
- Go to Credentials tab and copy the Client Secret
2. Assign Required Roles to Client
For the plugin to fetch user roles, the client needs realm-management permissions:
- Go to Clients →
strapi-admin→ Service Account Roles - Click Assign role
- Filter by realm-management client
- Assign these roles:
view-usersview-realmmanage-users(optional, for future features)
3. Create Keycloak Roles
- Go to Realm Roles → Create Role
- Create roles that will map to Strapi admin roles:
STRAPI_SUPER_ADMINSTRAPI_EDITORSTRAPI_AUTHOR
4. Assign Roles to Users
- Go to Users → Select a user → Role Mapping
- Assign the appropriate Keycloak role
Role Mapping
Managing Mappings via Admin UI
- Log in to Strapi Admin Panel
- Navigate to Settings → Keycloak Passport
- Map Keycloak roles to Strapi admin roles
- Click Save
Example Mapping
| Keycloak Role | Strapi Role |
|---|---|
STRAPI_SUPER_ADMIN | Super Admin (1) |
STRAPI_EDITOR | Editor (2) |
STRAPI_AUTHOR | Author (3) |
How It Works
- User logs in with Keycloak credentials
- Plugin fetches user's Keycloak roles
- Roles are mapped to Strapi roles using saved mappings
- If no mapping exists, user gets the
defaultRoleIdrole - User is created/updated in Strapi with assigned roles
Authentication Flow
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ User │ │ Strapi │ │ Keycloak │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
│ 1. POST /admin/login │ │
│ (email + password) │ │
│─────────────────────────────────>│ │
│ │ │
│ │ 2. OAuth2 Password Grant │
│ │─────────────────────────────────>│
│ │ │
│ │ 3. Access Token │
│ │<─────────────────────────────────│
│ │ │
│ │ 4. GET /userinfo │
│ │─────────────────────────────────>│
│ │ │
│ │ 5. User Info + Roles │
│ │<─────────────────────────────────│
│ │ │
│ │ 6. Find/Create Admin User │
│ │ 7. Map Roles │
│ │ 8. Generate Strapi JWT │
│ │ │
│ 9. JWT Token + User │ │
│<─────────────────────────────────│ │
│ │ │API Endpoints
All endpoints are prefixed with /strapi-keycloak-passport/
| Method | Endpoint | Description | Auth |
|---|---|---|---|
POST | /admin/login | Authenticate via Keycloak | No |
GET | /keycloak-roles | Fetch available Keycloak & Strapi roles | Yes |
GET | /get-keycloak-role-mappings | Get saved role mappings | Yes |
POST | /save-keycloak-role-mappings | Save role mappings | Yes |
GET | /test-connection | Test Keycloak connectivity | Yes |
GET | /token-cache-stats | Get token cache statistics | Yes |
POST | /invalidate-token | Invalidate cached admin token | Yes |
Features in Detail
Token Caching
Admin tokens are cached in-memory with automatic refresh:
- Tokens are cached using a composite key:
serverUrl:realm:clientId - Automatic refresh triggered 60 seconds before expiry
- Cache is invalidated when configuration changes
- Monitor cache via
/token-cache-statsendpoint
Audit Logging
All authentication events are logged to the database:
| Event | Logged Data |
|---|---|
| Login Success | User email, Keycloak ID, assigned roles, IP, user agent |
| Login Failure | Attempted email, failure reason, IP, user agent |
| User Created | Email, Strapi ID, Keycloak ID, assigned roles |
| User Updated | Email, changed fields (roles, name, etc.) |
| Role Mapping Changed | Keycloak role, Strapi role, performed by |
Query audit logs via Strapi's Content Manager or API.
Error Handling
The plugin implements a sanitized error pattern:
- Internal errors are logged with full details for debugging
- Client responses contain safe, generic messages
- Sensitive information (tokens, secrets) never exposed in responses
Security Considerations
- Client Secret: Store securely in environment variables, never commit
- Token Storage: Admin tokens cached in-memory only, never persisted
- Cookies: HttpOnly, Secure (in production), SameSite protection
- Input Validation: All inputs validated before processing
- Audit Trail: All authentication events logged for compliance
Troubleshooting
"Failed to authenticate with Keycloak"
- Verify
KEYCLOAK_AUTH_URLis correct (no trailing slash) - Check if
KEYCLOAK_LEGACY_MODEmatches your Keycloak version - Confirm client secret is correct
- Ensure client has proper service account roles
"Failed to fetch roles from Keycloak"
- Verify the client has
view-usersandview-realmroles assigned - Check Keycloak server logs for permission errors
"User gets wrong role"
- Check role mappings in Admin Panel
- Verify user has the expected role in Keycloak
- Check if role is in
excludedRolesconfiguration
Test Connection
Use the built-in connection test:
curl -X GET "https://your-strapi.com/strapi-keycloak-passport/test-connection" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"Changelog
v0.3.0
- Added Keycloak 17+ support with
KEYCLOAK_LEGACY_MODEoption - Implemented token caching with automatic refresh
- Added comprehensive audit logging
- Refactored to centralized constants (no magic values)
- Implemented error sanitization pattern
- Added new endpoints:
/test-connection,/token-cache-stats,/invalidate-token - Full JSDoc documentation
- Simplified configuration (removed
KEYCLOAK_TOKEN_URL,KEYCLOAK_USERINFO_URL)
v0.2.x
- Initial release with basic Keycloak authentication
- Role mapping UI
- Strapi v5 compatibility
Contributing
Contributions are welcome! Please read our contributing guidelines before submitting PRs.
License
MIT License - see LICENSE for details.
Support
Install now
npm install strapi-keycloak-passport
Create your own plugin
Check out the available plugin resources that will help you to develop your plugin or provider and get it listed on the marketplace.