Skip to content

brakmic/passport-keycloak-oauth2-oidc-portable

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

passport-keycloak-oauth2-oidc-portable

Passport strategy for authenticating with Keycloak using OAuth2/OIDC.

Table of Contents

  1. Why I Did This
  2. What's New
  3. Installation
  4. Usage
  5. Development Environment
  6. Testing
  7. Understanding PKCE
  8. Additional Information
  9. License

Why I Did This

The original passport-keycloak-oauth2-oidc wasn't up to date. I modernized it with improved PKCE support, standalone client examples, and TypeScript support. Check out my blog for tutorials: blog.brakmic.com.

What's New in This Fork?

  • TypeScript Only: The project is now TypeScript-based, with no JavaScript code.
  • PKCE Support: Full Proof Key for Code Exchange (PKCE) implementation for public clients.
  • Standalone Public Client: A single self-contained example demonstrating PKCE.
  • Keycloak via Docker Compose: Simplified container-based setup.

Installation

npm install passport-keycloak-oauth2-oidc-portable
pnpm add passport-keycloak-oauth2-oidc-portable
yarn add passport-keycloak-oauth2-oidc-portable

Usage

Create an Application

  1. Configure your Keycloak realm
  2. Create a client (public or confidential)
  3. Set valid redirect URIs
  4. Enable PKCE if using public client

Configure Strategy

import passport from 'passport';
import KeycloakStrategy from 'passport-keycloak-oauth2-oidc-portable';

passport.use(new KeycloakStrategy({
    clientID: 'your-client-id',
    realm: 'your-realm',
    publicClient: true,
    authServerURL: 'http://localhost:3000',
    callbackURL: 'http://localhost:3002/auth/callback',
    pkce: true,
    state: true
  },
  (accessToken, refreshToken, profile, done) => {
    return done(null, profile);
  }
));

Complete Example

import express from 'express';
import session from 'express-session';
import passport from 'passport';
import KeycloakStrategy from 'passport-keycloak-oauth2-oidc-portable';

const app = express();

app.use(session({
  secret: 'your-secret',
  resave: false,
  saveUninitialized: false,
  cookie: {
    secure: false,
    maxAge: 1000 * 60 * 60 * 24
  }
}));

app.use(passport.initialize());
app.use(passport.session());

passport.serializeUser((user, done) => done(null, user));
passport.deserializeUser((user, done) => done(null, user));

passport.use(new KeycloakStrategy({
  clientID: 'test-client',
  realm: 'TestRealm',
  publicClient: true,
  authServerURL: 'http://localhost:3000',
  callbackURL: 'http://localhost:3002/auth/callback',
  pkce: true,
  state: true
}, (accessToken, refreshToken, profile, done) => {
  return done(null, { ...profile, accessToken });
}));

app.get('/auth/keycloak', passport.authenticate('keycloak'));

app.get('/auth/callback',
  passport.authenticate('keycloak', {
    successRedirect: '/profile',
    failureRedirect: '/login',
    failureFlash: true
  })
);

app.get('/profile',
  ensureAuthenticated,
  (req, res) => {
    res.json({ user: req.user });
  }
);

function ensureAuthenticated(req, res, next) {
  if (req.isAuthenticated()) return next();
  res.redirect('/auth/keycloak');
}

app.listen(3002);

Development Environment

Docker Services

Service Internal URL External URL Purpose Ports Networks
Keycloak http://testcloak:8080 http://localhost:3000 Auth Server 8080, 9000 devnetwork
NGINX http://test-proxy:8080 http://localhost:3000 Proxy 3000, 8080 devnetwork
E2E Server http://e2e-server:4000 N/A Protected API 4000 devnetwork
Public Client http://localhost:3002 http://localhost:3002 Example App 3002 host

Available Scripts

Script Purpose Usage
setup:test-env Start test environment yarn setup:test-env
setup:test-env:force Force restart environment yarn setup:test-env:force
start:public-client Run example client yarn start:public-client
test:integration Run integration tests yarn test:integration
test:e2e Run E2E tests yarn test:e2e
test:unit Run unit tests yarn test:unit
test Run all tests yarn test

Testing

Test Environment

The test environment consists of:

  • Keycloak server (authentication)
  • NGINX proxy (routing)
  • E2E server (protected resources)
  • Test realm with predefined users

Running Tests

# Start environment
yarn setup:test-env

# Run specific tests
yarn test:unit
yarn test:integration
yarn test:e2e

# Run all tests
yarn test

Understanding PKCE

PKCE (Proof Key for Code Exchange) is a security extension for OAuth 2.0 used with public clients. The implementation:

  1. Generates a code verifier (random string)
  2. Creates a code challenge (SHA-256 hash of verifier)
  3. Sends challenge with auth request
  4. Sends verifier with token request
// PKCE Implementation Example
const { code_verifier, code_challenge } = generatePkcePair();
// code_verifier is stored in session
// code_challenge is sent with authorization request

Additional Information

Accessing Services

Default Credentials

  • Keycloak Admin: admin/admin
  • Test User: test-user/password

License

MIT

About

A Passport.js strategy for authenticating with Keycloak using the OAuth2/OIDC API (portable version)

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 54.4%
  • JavaScript 40.6%
  • Shell 3.9%
  • Other 1.1%