Passport Strategy Base Class
The `passport-strategy` package provides an abstract `Strategy` class that serves as the foundational interface for implementing concrete authentication strategies within the Passport.js ecosystem. It defines the core API, including the `authenticate()` method and helper functions like `success()`, `fail()`, `redirect()`, `pass()`, and `error()`, which custom strategies must implement or utilize to manage the authentication flow. While the core `passport` package is actively maintained (latest version ~0.7.0 as of late 2023), the `passport-strategy` package itself, version 1.0.0, has not seen updates since 2013, making it a very stable but effectively unmaintained base. Developers primarily interact with this module by extending its `Strategy` class to create custom authentication logic (e.g., `passport-local`, `passport-github`). Its key differentiator is its role as the common contract for all Passport strategies, enabling a highly modular and extensible authentication system for Node.js applications.
Common errors
-
TypeError: Strategy is not a constructor
cause Attempting to use `new Strategy()` after incorrectly importing it as a named export in CommonJS, or a general incorrect import path.fixIn CommonJS, ensure you use `const Strategy = require('passport-strategy');`. In ESM/TypeScript, ensure your transpilation handles `module.exports` correctly, often `import Strategy from 'passport-strategy';` is needed, or potentially `import { Strategy } from 'passport-strategy';` if tooling assumes named export behavior. -
TypeError: Strategy#authenticate must be overridden by subclass
cause You are attempting to use the abstract `Strategy` class directly without extending it and implementing your own `authenticate` method.fixCreate a subclass that extends `Strategy` and provides its own `authenticate(req, options)` method with your authentication logic. `class MyStrategy extends Strategy { authenticate(req, options) { /* ... */ } }` -
TypeError: Cannot read properties of undefined (reading 'user') on req.user after authentication
cause This typically indicates that `passport.initialize()` and/or `passport.session()` middleware are not correctly configured, or `passport.serializeUser`/`deserializeUser` are missing or misconfigured, preventing the authenticated user from being attached to the request.fixVerify that `app.use(passport.initialize());` and `app.use(passport.session());` (if using sessions) are correctly placed before any routes that require authentication. Also, ensure `passport.serializeUser` and `passport.deserializeUser` are implemented to manage user sessions.
Warnings
- breaking The `passport-strategy` package (v1.0.0) is very old, last published in 2013, and has not received updates in over a decade. While still functional as a base class, developers should be aware that it might not align with the latest Node.js features, security best practices, or modern JavaScript syntax (e.g., pure ESM).
- gotcha `passport-strategy` exports the `Strategy` constructor directly as `module.exports`, not as a named export. Attempting `const { Strategy } = require('passport-strategy');` in CommonJS environments will result in `undefined` for `Strategy`.
- gotcha The `Strategy` class is abstract and *must* be subclassed. Instantiating `new Strategy()` directly and calling `authenticate()` without overriding it will result in an error or unexpected behavior, as the abstract `authenticate` method is not implemented in the base class.
- gotcha This package only provides the base class. To use custom strategies within an application, you must also install and configure the main `passport` package, including its middleware (`passport.initialize()` and `passport.session()`) and `serializeUser`/`deserializeUser` functions for session management.
Install
-
npm install passport-strategy -
yarn add passport-strategy -
pnpm add passport-strategy
Imports
- Strategy
const Strategy = require('passport-strategy').Strategy;import { Strategy } from 'passport-strategy'; - Strategy (CommonJS)
const { Strategy } = require('passport-strategy');const Strategy = require('passport-strategy');
Quickstart
const util = require('util');
const Strategy = require('passport-strategy');
/**
* A simple custom strategy extending passport-strategy.
* This example demonstrates a basic 'always success' strategy.
*/
function CustomAlwaysSuccessStrategy(options) {
Strategy.call(this);
this.name = 'custom-always-success';
this._options = options || {};
}
util.inherits(CustomAlwaysSuccessStrategy, Strategy);
/**
* The authenticate method must be overridden by subclasses.
* It performs the actual authentication logic.
*/
CustomAlwaysSuccessStrategy.prototype.authenticate = function(req, options) {
// In a real strategy, you would parse credentials from req,
// interact with a database, call an external API, etc.
// For this example, we simply succeed immediately with a dummy user.
const user = { id: '123', name: 'Test User' };
const info = { message: 'Authentication successful with custom strategy.' };
// Call one of the action functions provided by the base Strategy class.
// This indicates the outcome of the authentication attempt.
this.success(user, info);
// Other possible outcomes:
// this.fail({ message: 'Invalid credentials' }, 401);
// this.redirect('/login', 302);
// this.pass(); // defer to next strategy
// this.error(new Error('Something went wrong'));
};
// Example usage with Passport.js (requires 'passport' package)
const passport = require('passport');
passport.use(new CustomAlwaysSuccessStrategy());
// To test, imagine an Express route:
// app.get('/auth/custom', passport.authenticate('custom-always-success', { session: false }), (req, res) => {
// res.json({ message: 'Logged in!', user: req.user });
// });
// For demonstration, let's manually 'authenticate' (without Express context)
// In a real app, this would be handled by Passport middleware.
const dummyReq = {}; // Simulate an Express request object
const strategyInstance = new CustomAlwaysSuccessStrategy();
strategyInstance.authenticate(dummyReq, {}, (err, user, info) => {
if (user) {
console.log('Authentication successful:', user, info);
} else {
console.error('Authentication failed:', err || info);
}
});