Grant Express Middleware

raw JSON →
5.4.8 verified Thu Apr 23 auth: no javascript

Grant Express is an Express.js middleware that acts as a handler for the Grant OAuth Proxy, simplifying authentication and authorization flows within Node.js applications. It integrates the robust Grant core library, which provides universal OAuth support for over 200 providers including Google, GitHub, Facebook, and many others. The current stable version for `grant-express` is 5.4.8. Grant is designed to abstract away the complexities of OAuth 1.0a, 2.0, and OpenID Connect, offering a unified configuration system and flexible integration with various HTTP frameworks and serverless environments. Its key differentiators include broad provider compatibility, a declarative configuration approach, and its ability to function as an embeddable OAuth client. The package facilitates managing OAuth callbacks, tokens, and session state efficiently, though users must provide their own session store. Release cadence is tied to the underlying Grant core library, which is actively maintained with updates for new providers, OAuth specification changes, and security patches.

error Error: Grant: session store is required
cause The `grant-express` middleware was initialized and used without a preceding session middleware (like `express-session`). Grant relies on sessions to manage state across OAuth redirects.
fix
Ensure express-session (or an equivalent session management middleware) is installed and configured using app.use(session({ ... })) *before* mounting grant-express with app.use(Grant(config)).
error OAuth error: redirect_uri_mismatch
cause The callback URL configured for your application on the OAuth provider's website does not exactly match the `redirect_uri` that Grant generates based on your `origin`, `prefix`, and provider configuration.
fix
Double-check your Grant configuration (origin, prefix, and provider callback) and compare it precisely with the Authorized Redirect URIs listed in your OAuth provider's application settings. Pay attention to http vs https, domain, port, and path segments.
error TypeError: Grant is not a function
cause The `grant-express` module was imported or required incorrectly, or you are attempting to use it as a named export when it is a default export (or vice-versa for CommonJS).
fix
For ES Modules, use import Grant from 'grant-express';. For CommonJS, use const Grant = require('grant-express');. Ensure you are calling the imported Grant function to create the middleware, e.g., app.use(Grant(config)).
error Cannot GET /connect/provider or Cannot POST /callback
cause The `grant-express` middleware is either not mounted in your Express application, or its configured `prefix` does not match the URL paths being accessed, causing Express to not find a handler.
fix
Verify that app.use(Grant(config)) is called correctly in your Express setup. Confirm that the prefix in your grantConfig matches the base path from which you expect Grant to handle routes (e.g., if prefix: '/auth', then /auth/github would initiate the flow).
breaking Express v5 introduced several breaking changes. While `grant-express` has a peer dependency on `express` `>=3.0.0`, ensuring full compatibility with the latest `express` v5 might require explicit updates to the `grant` core library or specific configuration adjustments. Consult the `express` migration guide and the `grant` documentation for any known incompatibilities.
fix Review your Express application for v5 breaking changes. Ensure `grant` (the core library) is updated to its latest version, which typically includes compatibility fixes for newer Express releases. Test thoroughly after upgrading `express`.
gotcha Grant requires a session middleware (e.g., `express-session`) to persist necessary state during the OAuth redirect flow. If not configured or placed correctly before `Grant` middleware, it will lead to runtime errors or failed authentication.
fix Install and configure `express-session` (or a compatible session store) and ensure `app.use(session(...))` is called *before* `app.use(Grant(...))` in your Express application's middleware chain.
gotcha OAuth client IDs and secrets (e.g., `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET`) should never be hardcoded directly into your application code. This is a severe security risk.
fix Always use environment variables, a secrets management service, or a secure configuration file to load sensitive credentials. Tools like `dotenv` can help manage environment variables in development.
gotcha The OAuth `redirect_uri` (callback URL) must precisely match the URL registered with the OAuth provider (e.g., GitHub). Mismatches, including differences in `http` vs `https`, port numbers, or path segments, will cause `redirect_uri_mismatch` errors and prevent authentication.
fix Carefully verify that the `origin` and `prefix` in your Grant configuration, along with the specific provider's `callback` path, exactly match what you have configured in the OAuth provider's developer settings.
gotcha The `grant-express` package itself was last published five years ago, while the core `grant` project (which it relies on) appears to be more actively maintained. This could mean direct `grant-express` specific updates might be delayed, though core `grant` updates should still apply.
fix Monitor the `grant` (core) repository for updates and breaking changes, as `grant-express` effectively wraps its functionality. If new Express versions or critical Node.js environment changes cause issues, direct contribution or seeking updates to `grant-express` itself may be necessary.
npm install grant-express
yarn add grant-express
pnpm add grant-express

Demonstrates setting up Grant Express middleware with a basic Express server and GitHub OAuth for user authentication, including session management and environment variable usage for credentials.

import express from 'express';
import session from 'express-session';
import Grant from 'grant-express';
import dotenv from 'dotenv';

dotenv.config(); // Load environment variables

const app = express();
const port = process.env.PORT || 3000;

// IMPORTANT: Grant requires a session middleware
app.use(session({
  secret: process.env.SESSION_SECRET ?? 'your-very-secret-key-that-should-be-random',
  resave: false,
  saveUninitialized: false,
  cookie: { secure: process.env.NODE_ENV === 'production' }
}));

// Grant configuration for GitHub OAuth
const grantConfig = {
  defaults: {
    origin: `http://localhost:${port}`,
    transport: 'session',
    state: true
  },
  github: {
    key: process.env.GITHUB_CLIENT_ID ?? '',
    secret: process.env.GITHUB_CLIENT_SECRET ?? '',
    scope: ['user:email', 'read:user'],
    callback: '/callback'
  }
};

// Mount the Grant middleware
app.use(Grant(grantConfig));

// Route to initiate GitHub OAuth
app.get('/login/github', (req, res) => {
  // Redirects to /connect/github which Grant handles
  res.redirect('/connect/github');
});

// Callback route to handle OAuth response
app.get('/callback', (req, res) => {
  if (req.query.error) {
    return res.status(400).send(`OAuth Error: ${req.query.error_description || req.query.error}`);
  }
  // Grant places the OAuth response data in req.session.grant.response
  const { access_token, profile } = (req.session as any)?.grant?.response?.github?.raw || {};
  if (access_token) {
    res.send(`
      <h1>Authentication Successful!</h1>
      <p>Access Token: ${access_token}</p>
      <p>User Profile (partial): ${profile ? JSON.stringify(profile.data, null, 2) : 'N/A'}</p>
      <p><a href="/">Home</a></p>
    `);
  } else {
    res.status(500).send('Authentication failed: No access token received.');
  }
});

// Basic home route
app.get('/', (req, res) => {
  res.send(`
    <h1>Welcome to Grant Express Example</h1>
    <p><a href="/login/github">Login with GitHub</a></p>
  `);
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
  console.log('Ensure GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, and SESSION_SECRET environment variables are set.');
});