Passport Keycloak Bearer Strategy

2.4.1 · active · verified Wed Apr 22

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.

Common errors

Warnings

Install

Imports

Quickstart

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.

import express from 'express';
import passport from 'passport';
import KeycloakBearerStrategy from 'passport-keycloak-bearer';

const app = express();

// --- IMPORTANT: Replace with your actual Keycloak configuration ---
const KEYCLOAK_URL = process.env.KEYCLOAK_AUTH_URL ?? 'https://your-keycloak-instance.com/auth';
const KEYCLOAK_REALM = process.env.KEYCLOAK_REALM ?? 'your-realm';
// ------------------------------------------------------------------

passport.use(new KeycloakBearerStrategy({
    url: KEYCLOAK_URL,
    realm: KEYCLOAK_REALM,
    passReqToCallback: false // Set to true if your verify callback needs the request object
}, (jwtPayload, done) => {
    // In a real application, you would fetch user details from a DB
    // or create a user object based on the JWT payload (e.g., jwtPayload.sub)
    const user = { id: jwtPayload.sub, username: jwtPayload.preferred_username, roles: jwtPayload.realm_access?.roles };
    
    // Example: only allow users with 'api-user' role
    if (user.roles && user.roles.includes('api-user')) {
      return done(null, user); // User authenticated successfully
    } else {
      return done(null, false, { message: 'User does not have required roles.' }); // Authentication failed
    }
}));

app.use(passport.initialize());

// A protected route
app.get('/api/protected', passport.authenticate('keycloak-bearer', { session: false }), (req, res) => {
    // req.user will contain the user object returned from the verify callback
    res.json({ message: 'Access granted!', user: req.user });
});

// Public route
app.get('/api/public', (req, res) => {
    res.json({ message: 'This is a public endpoint.' });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Server running on http://localhost:${PORT}`);
    console.log(`Test with curl -H "Authorization: Bearer <YOUR_KEYCLOAK_JWT_TOKEN>" http://localhost:${PORT}/api/protected`);
});

view raw JSON →