npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

strapi-keycloak-passport

v0.3.2

Published

Keycloak authentication provider for the Strapi v5 administration panel.

Readme

Strapi Keycloak Passport Plugin

Enterprise-grade Keycloak authentication for Strapi v5 Admin Panel with full RBAC support.

npm version License: MIT Strapi v5

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-passport

or

npm install strapi-keycloak-passport

Configuration

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=1

Keycloak 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

  1. Navigate to Keycloak Admin ConsoleClients
  2. Click Create Client:
    • Client ID: strapi-admin
    • Client Protocol: openid-connect
    • Client Authentication: On (Confidential)
  3. 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
  4. 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:

  1. Go to Clientsstrapi-adminService Account Roles
  2. Click Assign role
  3. Filter by realm-management client
  4. Assign these roles:
    • view-users
    • view-realm
    • manage-users (optional, for future features)

3. Create Keycloak Roles

  1. Go to Realm RolesCreate Role
  2. Create roles that will map to Strapi admin roles:
    • STRAPI_SUPER_ADMIN
    • STRAPI_EDITOR
    • STRAPI_AUTHOR

4. Assign Roles to Users

  1. Go to Users → Select a user → Role Mapping
  2. Assign the appropriate Keycloak role

Role Mapping

Managing Mappings via Admin UI

  1. Log in to Strapi Admin Panel
  2. Navigate to SettingsKeycloak Passport
  3. Map Keycloak roles to Strapi admin roles
  4. 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

  1. User logs in with Keycloak credentials
  2. Plugin fetches user's Keycloak roles
  3. Roles are mapped to Strapi roles using saved mappings
  4. If no mapping exists, user gets the defaultRoleId role
  5. 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-stats endpoint

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"

  1. Verify KEYCLOAK_AUTH_URL is correct (no trailing slash)
  2. Check if KEYCLOAK_LEGACY_MODE matches your Keycloak version
  3. Confirm client secret is correct
  4. Ensure client has proper service account roles

"Failed to fetch roles from Keycloak"

  1. Verify the client has view-users and view-realm roles assigned
  2. Check Keycloak server logs for permission errors

"User gets wrong role"

  1. Check role mappings in Admin Panel
  2. Verify user has the expected role in Keycloak
  3. Check if role is in excludedRoles configuration

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_MODE option
  • 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