{"id":17326,"library":"passport-keycloak-bearer","title":"Passport Keycloak Bearer Strategy","description":"Passport-Keycloak-Bearer is an HTTP Bearer authentication strategy designed for Passport.js, enabling Node.js applications to authenticate requests against a Keycloak identity provider using OAuth 2.0 bearer tokens. This package, currently at version 2.4.1, integrates seamlessly with Connect-style middleware frameworks like Express.js. It focuses on extracting, validating, and propagating JWT claims from access tokens to a `verify` callback, allowing developers to process user information and attach it to `req.user`. While there isn't an explicit release cadence mentioned, the versioning suggests ongoing maintenance. Its key differentiator is the direct integration with Keycloak's token validation, simplifying the setup for Keycloak-backed applications compared to generic JWT strategies that require manual configuration of Keycloak's public keys and issuer metadata.","status":"active","version":"2.4.1","language":"javascript","source_language":"en","source_url":"https://github.com/hgranlund/passport-keycloak-bearer","tags":["javascript","passport-keycloak-bearer","keycloak","passport","auth","oauth","bearer","authn","authentication","typescript"],"install":[{"cmd":"npm install passport-keycloak-bearer","lang":"bash","label":"npm"},{"cmd":"yarn add passport-keycloak-bearer","lang":"bash","label":"yarn"},{"cmd":"pnpm add passport-keycloak-bearer","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core authentication middleware that this strategy plugs into.","package":"passport","optional":false},{"reason":"Used internally for JWT token verification, configurable via jsonWebTokenOptions.","package":"jsonwebtoken","optional":false}],"imports":[{"note":"The strategy is exported as a default export, not a named export. It should be imported directly.","wrong":"import { KeycloakBearerStrategy } from 'passport-keycloak-bearer'","symbol":"KeycloakBearerStrategy","correct":"import KeycloakBearerStrategy from 'passport-keycloak-bearer'"},{"note":"While CommonJS `require` still works in Node.js, modern projects typically use ESM imports. Passport itself is commonly imported as a default export.","wrong":"const passport = require('passport')","symbol":"passport","correct":"import passport from 'passport'"},{"note":"For TypeScript users, import type definitions for options to ensure type safety without bundling the actual strategy code.","symbol":"Strategy Options (Type)","correct":"import type { IKeycloakBearerStrategyOptions } from 'passport-keycloak-bearer'"}],"quickstart":{"code":"import express from 'express';\nimport passport from 'passport';\nimport KeycloakBearerStrategy from 'passport-keycloak-bearer';\n\nconst app = express();\n\n// --- IMPORTANT: Replace with your actual Keycloak configuration ---\nconst KEYCLOAK_URL = process.env.KEYCLOAK_AUTH_URL ?? 'https://your-keycloak-instance.com/auth';\nconst KEYCLOAK_REALM = process.env.KEYCLOAK_REALM ?? 'your-realm';\n// ------------------------------------------------------------------\n\npassport.use(new KeycloakBearerStrategy({\n    url: KEYCLOAK_URL,\n    realm: KEYCLOAK_REALM,\n    passReqToCallback: false // Set to true if your verify callback needs the request object\n}, (jwtPayload, done) => {\n    // In a real application, you would fetch user details from a DB\n    // or create a user object based on the JWT payload (e.g., jwtPayload.sub)\n    const user = { id: jwtPayload.sub, username: jwtPayload.preferred_username, roles: jwtPayload.realm_access?.roles };\n    \n    // Example: only allow users with 'api-user' role\n    if (user.roles && user.roles.includes('api-user')) {\n      return done(null, user); // User authenticated successfully\n    } else {\n      return done(null, false, { message: 'User does not have required roles.' }); // Authentication failed\n    }\n}));\n\napp.use(passport.initialize());\n\n// A protected route\napp.get('/api/protected', passport.authenticate('keycloak-bearer', { session: false }), (req, res) => {\n    // req.user will contain the user object returned from the verify callback\n    res.json({ message: 'Access granted!', user: req.user });\n});\n\n// Public route\napp.get('/api/public', (req, res) => {\n    res.json({ message: 'This is a public endpoint.' });\n});\n\nconst PORT = process.env.PORT || 3000;\napp.listen(PORT, () => {\n    console.log(`Server running on http://localhost:${PORT}`);\n    console.log(`Test with curl -H \"Authorization: Bearer <YOUR_KEYCLOAK_JWT_TOKEN>\" http://localhost:${PORT}/api/protected`);\n});\n","lang":"typescript","description":"This quickstart demonstrates how to set up an Express application with Passport.js and `passport-keycloak-bearer` to protect an API endpoint. It initializes the strategy with Keycloak URL and realm, defines a `verify` callback to process the JWT payload and attach a user object to `req.user`, and uses `passport.authenticate` middleware to secure a route."},"warnings":[{"fix":"Refer to the documentation for the specific major version you are targeting. Upgrade to the latest stable version and adapt your code as per the new API.","message":"Older versions (pre-2.x) of `passport-keycloak-bearer` might have different constructor signatures or option configurations. Always consult the specific version's README for exact usage, especially when upgrading across major versions.","severity":"breaking","affected_versions":"<2.0.0"},{"fix":"Double-check `url` and `realm` against your Keycloak server's configuration. Ensure the URL points to the base authentication endpoint (e.g., `https://keycloak.dev.org/auth`) and not directly to realm-specific endpoints or token URLs.","message":"The `url` and `realm` options are critically important and must accurately point to your Keycloak server and specific realm. Misconfigurations here will lead to failed token validation or inability to retrieve public keys.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Avoid setting `ignoreExpiration: true` in production environments. Ensure your client applications handle token refreshing proactively before expiration. If you must ignore expiration (e.g., for specific testing), understand the security implications.","message":"By default, `passport-keycloak-bearer` validates the token's expiration. If `ignoreExpiration` is set to `true` (which is generally discouraged in production for security reasons), expired tokens will still be accepted.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always ensure your `verify` callback calls `done(null, user)` for a successful authentication, `done(null, false)` for failed authentication (e.g., invalid credentials or insufficient roles), and `done(error)` for an error during verification (e.g., database lookup failure). Review Passport's documentation for `done` callback patterns.","message":"The `verify` callback is responsible for determining if a user is successfully authenticated and what user object should be attached to `req.user`. Incorrectly calling `done(null, false)` or `done(error)` can lead to unexpected authentication failures or errors.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Ensure the client is sending a request with an `Authorization: Bearer <your_jwt_token>` header. Verify the token format and that it's present in the request.","cause":"The incoming HTTP request does not contain an `Authorization` header with a `Bearer` token, or the token is malformed.","error":"Error: bearer token not found"},{"fix":"Check the `alg` header in your JWT token and ensure it's included in the `algorithms` array option when initializing `KeycloakBearerStrategy`. For Keycloak, this is typically `RS256` or `PS256` for production environments.","cause":"The JWT token's signing algorithm does not match any of the algorithms specified in the `algorithms` option passed to `KeycloakBearerStrategy`.","error":"JsonWebTokenError: invalid algorithm"},{"fix":"Obtain a new, valid (unexpired) JWT token from Keycloak. Implement a token refresh mechanism on the client side to proactively renew tokens before they expire. If strictly necessary for testing, set `ignoreExpiration: true` (with caution).","cause":"The provided JWT bearer token has exceeded its `exp` (expiration) claim and is no longer valid, and `ignoreExpiration` is not set to `true`.","error":"TokenExpiredError: jwt expired"}],"ecosystem":"npm","meta_description":null}