Keycloak SSO
Adds Keycloak single sign-on to Payload CMS 3 via an OIDC auth strategy with PKCE, silent token refresh, and permission-based access control.
Installation
pnpm add payload-keycloak About
This plugin adds Keycloak single sign-on to Payload CMS 3. It registers a `keycloak` auth strategy that verifies Keycloak access tokens offline against JWKS and the issuer, fetches `/userinfo` (cached per token), and attaches a permissions claim to `req.user`. Payload's local auth strategy is disabled, so there are no local users or passwords; users are created on first login by their Keycloak `sub`, and `email`, `name`, and `keycloakSub` fields are added to the auth collection when missing. A first-login create race against the unique `keycloakSub` index is retried as a lookup, so parallel initial requests do not silently fail. Admin login uses the Authorization Code flow with PKCE (S256) against a public Keycloak client. The default `/admin/login` view redirects straight to Keycloak through a `beforeLogin` server component, and the callback at `/api/auth/callback` sets the session cookies and returns to `/admin`. An expired access token in the cookie is silently refreshed using the refresh-token cookie, so Payload's inactivity timers follow the Keycloak SSO session; `/api/users/me` reports the refresh token's `exp`, and `/api/users/refresh-token` and `/api/users/logout` are wired up. Logout clears the cookies and hands off to Keycloak's end-session endpoint with an `id_token_hint`. Permissions are read from a userinfo claim (default `permissions`) as nested booleans, for example `{ posts: { edit: true } }`. The helpers `authenticated`, `can('posts.edit')`, `withKeycloakAccess`, `withKeycloakGlobalAccess`, `withAuth`, and `permissionsOf` compose those rules on top of each collection's existing access rather than replacing it. Configuration requires `url`, `realm`, `clientId`, and `serverURL`; other options include `basePath`, `usersSlug`, `scope`, `allowedOrigins`, `permissionsClaim`, `userInfoTtl`, `internalHosts`, `messages`, and `enabled`. The only runtime dependency is `jose`. Notable limits: `aud` is not validated, so access is gated with permissions instead. The userinfo cache and refresh coalescing live in process memory, which suits a single replica. Keycloak's "Revoke Refresh Token" must be off, because admin pages are server-rendered without `canSetHeaders` and cannot write rotated cookies back. The access token is a Keycloak realm credential, so the plugin forces `auth.removeTokenFromResponses` and keeps it in the httpOnly cookie, never in the `me` or `refresh-token` JSON body.
Package info
- Package name
payload-keycloak- Latest version
1.0.1- Unpacked size
- 118 kB
- License
- MIT
- Weekly downloads
- 16
- Last publish
- Sep 16, 2026
Similar plugins
More in AuthBetter Auth
Better Auth adapter and plugins for Payload CMS.
Passkey
Adds WebAuthn passkey login and management to Payload CMS accounts via Better Auth.
TOTP
Add an extra layer of security with Time-based One-time Passwords (TOTP).
Subscribers
Manage subscribers and channels with magic link authentication.
Simple Social Login
Adds Google and Microsoft (Entra ID) OAuth social login buttons to the Payload admin panel and authenticated collections.
payload-auth
Integrates Better Auth for enhanced authentication in Payload CMS.