Passport OAuth2 Client Password Strategy
passport-oauth2-client-password is an authentication strategy module designed for the Passport.js middleware framework, specifically implementing the OAuth 2.0 client password grant type. It allows applications to authenticate client credentials (client ID and client secret) when provided in the request body, a common pattern for securing OAuth 2.0 token endpoints. The current stable version is 0.1.2. The package's last publish was 11 years ago, and its GitHub repository shows no recent activity, indicating it is no longer actively maintained. Its primary differentiator lies in providing a focused, simple implementation for this specific OAuth2 authentication mechanism within the Passport ecosystem. However, its age means it likely lacks modern JavaScript features, TypeScript definitions (though `@types/passport-oauth2-client-password` exists), and contemporary security updates. Developers should consider its abandoned status and potential compatibility issues with newer Node.js versions when evaluating its use.
Common errors
-
Error: Cannot find module 'passport-oauth2-client-password'
cause The package is not installed or the module resolution path is incorrect.fixEnsure the package is installed: `npm install passport-oauth2-client-password`. If using a non-standard module path, verify the path. -
TypeError: ClientPasswordStrategy is not a constructor
cause This error typically occurs if you try to import the strategy using a named import (e.g., `import { ClientPasswordStrategy } from '...'`) or destructure it incorrectly from a `require` statement, or if the `require` statement itself fails.fixUse the correct CommonJS `require` syntax as the module directly exports the constructor: `const ClientPasswordStrategy = require('passport-oauth2-client-password');`. -
Client authentication failing (verify callback returning `done(null, false)`)
cause The `verify` callback function within the strategy is returning `done(null, false)`, indicating that the provided `clientId` or `clientSecret` does not match your stored client credentials.fixInspect the `clientId` and `clientSecret` values passed to the `verify` callback and compare them against your mock or database records. Ensure they match exactly and that your client lookup logic is correct. Log the input credentials and your stored clients for debugging.
Warnings
- breaking This package is effectively abandoned, with the last publish being over a decade ago. It has not received updates for new Node.js versions, security patches, or modern JavaScript features. Use with caution in production environments, especially regarding security vulnerabilities and compatibility.
- gotcha This strategy is specifically designed for OAuth 2.0 client password authentication (client_id and client_secret in the request body) and not for authenticating end-users directly. It's typically used at a token endpoint to verify the requesting client application.
- gotcha The package does not officially support ESM (ECMAScript Modules). Using `import` statements will result in runtime errors due to Node.js's CJS/ESM interoperability rules for older packages.
Install
-
npm install passport-oauth2-client-password -
yarn add passport-oauth2-client-password -
pnpm add passport-oauth2-client-password
Imports
- ClientPasswordStrategy
import ClientPasswordStrategy from 'passport-oauth2-client-password';
const ClientPasswordStrategy = require('passport-oauth2-client-password'); - Strategy (named destructure)
const { Strategy } = require('passport-oauth2-client-password');const Strategy = require('passport-oauth2-client-password'); - ClientPasswordStrategy (Type)
import type { ClientPasswordStrategy } from 'passport-oauth2-client-password';import type { Strategy as ClientPasswordStrategy } from 'passport-oauth2-client-password';
Quickstart
const express = require('express');
const passport = require('passport');
const ClientPasswordStrategy = require('passport-oauth2-client-password');
const app = express();
const port = 3000;
// Middleware to parse request body (e.g., for client_id and client_secret)
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
// Initialize Passport middleware
app.use(passport.initialize());
// --- Mock Database (in a real app, this would be a database query) ---
const clients = [
{ id: 1, clientId: 'client123', clientSecret: 'secret123', name: 'Test Client' },
{ id: 2, clientId: 'anotherClient', clientSecret: 'superSecret', name: 'Another Test Client' },
];
// --- End Mock Database ---
// Configure the Client Password strategy
passport.use(new ClientPasswordStrategy(
function(clientId, clientSecret, done) {
console.log(`Attempting to authenticate client: ${clientId}`);
const client = clients.find(c => c.clientId === clientId);
if (!client) {
console.log('Client not found.');
// `done(null, false)` indicates authentication failure.
return done(null, false);
}
if (client.clientSecret !== clientSecret) {
console.log('Client secret mismatch.');
return done(null, false);
}
console.log(`Client '${client.name}' authenticated successfully.`);
// `done(null, client)` indicates success, attaching client to req.user
return done(null, client);
}
));
// Define a token endpoint (or any endpoint requiring client authentication)
app.post('/token',
// Authenticate using the 'oauth2-client-password' strategy
// `session: false` because clients typically don't establish sessions
passport.authenticate('oauth2-client-password', { session: false }),
(req, res) => {
// If we reach here, the client is authenticated (req.user will contain the client object)
console.log('Client authenticated successfully at /token endpoint.');
res.json({
message: 'Client authenticated successfully',
client: req.user // The authenticated client object
});
}
);
// Simple root endpoint for demonstration
app.get('/', (req, res) => {
res.send('Welcome! Try POSTing to /token with client_id and client_secret in the body (form-urlencoded or JSON).');
});
app.listen(port, () => {
console.log(`Server listening at http://localhost:${port}`);
console.log('\n--- Test Commands ---');
console.log(`curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "client_id=client123&client_secret=secret123" http://localhost:${port}/token`);
console.log(`curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "client_id=badclient&client_secret=badsecret" http://localhost:${port}/token`);
console.log(`curl -X POST -H "Content-Type: application/json" -d '{"client_id":"client123","client_secret":"secret123"}' http://localhost:${port}/token`);
});