OAuth 2.0 authentication strategy for Passport that enables developers to implement OAuth 2.0-based authentication in Node.js applications.
npx @tessl/cli install tessl/npm-passport-oauth2@1.8.0General-purpose OAuth 2.0 authentication strategy for Passport.js that enables developers to implement OAuth 2.0-based authentication in Node.js applications. It serves as a foundation for building provider-specific OAuth 2.0 strategies and integrates seamlessly with Connect-style middleware frameworks like Express.
npm install passport-oauth2// Main import (default export is the Strategy constructor)
const OAuth2Strategy = require('passport-oauth2');
// Named imports for strategy and error classes
const { Strategy, AuthorizationError, TokenError, InternalOAuthError } = require('passport-oauth2');ES Modules:
import OAuth2Strategy from 'passport-oauth2';
// Or with named imports
import { Strategy, AuthorizationError, TokenError, InternalOAuthError } from 'passport-oauth2';const passport = require('passport');
const OAuth2Strategy = require('passport-oauth2');
// Configure the strategy
passport.use(new OAuth2Strategy({
authorizationURL: 'https://www.example.com/oauth2/authorize',
tokenURL: 'https://www.example.com/oauth2/token',
clientID: 'your-client-id',
clientSecret: 'your-client-secret',
callbackURL: "http://localhost:3000/auth/example/callback"
},
function(accessToken, refreshToken, profile, done) {
// Find or create user based on profile
User.findOrCreate({ exampleId: profile.id }, function (err, user) {
return done(err, user);
});
}
));
// Use in Express routes
app.get('/auth/example', passport.authenticate('oauth2'));
app.get('/auth/example/callback',
passport.authenticate('oauth2', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
});Passport OAuth2 is built around several key components:
Core OAuth 2.0 authentication strategy that handles authorization flow, token exchange, and user profile retrieval.
/**
* Creates an OAuth2Strategy instance
* @param options - Configuration options for OAuth 2.0 provider
* @param verify - Callback function for user verification
*/
function OAuth2Strategy(options, verify);
interface OAuth2StrategyOptions {
authorizationURL: string; // Required: Authorization endpoint URL
tokenURL: string; // Required: Token endpoint URL
clientID: string; // Required: OAuth client identifier
clientSecret?: string; // Client secret for authentication
callbackURL?: string; // Redirect URI after authorization
scope?: string | string[]; // Requested access scope
scopeSeparator?: string; // Scope separator (default: ' ')
state?: boolean; // Enable CSRF protection
store?: boolean | object; // State store configuration
sessionKey?: string; // Session key for state storage
pkce?: boolean | string; // Enable PKCE ('S256', 'plain', or boolean)
proxy?: boolean; // Trust proxy headers
passReqToCallback?: boolean; // Pass request to verify callback
skipUserProfile?: boolean | SkipUserProfileFunction; // Skip profile retrieval
customHeaders?: object; // Custom headers for OAuth requests
}
/**
* Function to conditionally skip user profile loading
*/
type SkipUserProfileFunction = (
accessToken: string,
done: (err?: Error, skip?: boolean) => void
) => void;
/**
* Verify callback signatures
*/
type VerifyCallback = (
accessToken: string,
refreshToken: string,
profile: object,
done: (err?: Error, user?: any, info?: any) => void
) => void;
type VerifyCallbackWithParams = (
accessToken: string,
refreshToken: string,
params: object,
profile: object,
done: (err?: Error, user?: any, info?: any) => void
) => void;
type VerifyCallbackWithRequest = (
req: object,
accessToken: string,
refreshToken: string,
profile: object,
done: (err?: Error, user?: any, info?: any) => void
) => void;
type VerifyCallbackWithRequestAndParams = (
req: object,
accessToken: string,
refreshToken: string,
params: object,
profile: object,
done: (err?: Error, user?: any, info?: any) => void
) => void;Core methods available on OAuth2Strategy instances for authentication flow control and customization.
/**
* Main authentication method that handles OAuth 2.0 flow
* @param req - HTTP request object
* @param options - Authentication options
*/
OAuth2Strategy.prototype.authenticate = function(req, options);
/**
* Retrieve user profile from service provider (virtual method)
* @param accessToken - OAuth access token
* @param done - Callback function
*/
OAuth2Strategy.prototype.userProfile = function(accessToken, done);
/**
* Return extra parameters for authorization request (virtual method)
* @param options - Options object
* @returns Object with additional parameters
*/
OAuth2Strategy.prototype.authorizationParams = function(options);
/**
* Return extra parameters for token request (virtual method)
* @param options - Options object
* @returns Object with additional parameters
*/
OAuth2Strategy.prototype.tokenParams = function(options);
/**
* Parse error response from OAuth 2.0 endpoint (virtual method)
* @param body - Response body string
* @param status - HTTP status code
* @returns Error object or null
*/
OAuth2Strategy.prototype.parseErrorResponse = function(body, status);
/**
* Load user profile with conditional skipping (internal method)
* @param accessToken - OAuth access token
* @param done - Callback function
*/
OAuth2Strategy.prototype._loadUserProfile = function(accessToken, done);
/**
* Create OAuth error wrapper with provider-specific parsing (internal method)
* Attempts to parse error response, falls back to InternalOAuthError
* @param message - Error message
* @param err - Original error with statusCode and data
* @returns TokenError from parseErrorResponse or InternalOAuthError
*/
OAuth2Strategy.prototype._createOAuthError = function(message, err);Specialized error classes for different OAuth 2.0 failure scenarios with proper error codes and HTTP status mapping.
/**
* Authorization error representing OAuth authorization failures
* @param message - Error message
* @param code - OAuth error code
* @param uri - Error URI reference
* @param status - HTTP status code
*/
function AuthorizationError(message, code, uri, status);
/**
* Token error representing OAuth token endpoint failures
* @param message - Error message
* @param code - OAuth error code (default: 'invalid_request')
* @param uri - Error URI reference
* @param status - HTTP status code (default: 500)
*/
function TokenError(message, code, uri, status);
/**
* Internal OAuth error wrapping node-oauth errors
* @param message - Error message
* @param err - Original error object
*/
function InternalOAuthError(message, err);State store implementations for CSRF protection and PKCE support with multiple storage backends.
/**
* Full session-based state store with metadata support (from lib/state/store)
* @param options - Configuration options
*/
function StateStore(options);
/**
* Simple session-based nonce store for basic CSRF protection (from lib/state/session)
* @param options - Configuration options
*/
function SessionStore(options);
/**
* PKCE-enabled session state store with code verifier support (from lib/state/pkcesession)
* @param options - Configuration options
*/
function PKCESessionStore(options);
/**
* No-op state store that performs no validation (from lib/state/null)
* @param options - Configuration options
*/
function NullStore(options);
interface StateStoreOptions {
key: string; // Required: Session key for storing state
}Internal utility functions for URL reconstruction and object merging used by the OAuth2 flow.
/**
* Reconstructs the original URL of the request with protocol and host
* @param req - HTTP request object
* @param options - Configuration options for proxy handling
* @returns Complete URL string
*/
function originalURL(req, options);
/**
* Merge utility from utils-merge package
* @param destination - Target object
* @param source - Source object to merge
* @returns Merged object
*/
function merge(destination, source);
interface OriginalURLOptions {
proxy?: boolean; // Trust proxy headers for protocol detection
}/**
* Base Strategy class from passport-strategy
*/
interface Strategy {
name: string;
authenticate(req: any, options?: any): void;
success(user: any, info?: any): void;
fail(challenge?: any, status?: number): void;
redirect(url: string, status?: number): void;
pass(): void;
error(err: Error): void;
}
/**
* OAuth2Strategy class extending Strategy
*/
interface OAuth2Strategy extends Strategy {
name: 'oauth2';
_verify: VerifyCallback;
_oauth2: OAuth2Client;
_callbackURL?: string;
_scope?: string | string[];
_scopeSeparator: string;
_pkceMethod?: string;
_key: string;
_stateStore: StateStore;
_trustProxy?: boolean;
_passReqToCallback?: boolean;
_skipUserProfile: boolean | SkipUserProfileFunction;
}
/**
* OAuth2 client from node-oauth package
*/
interface OAuth2Client {
getOAuthAccessToken(code: string, params: any, callback: (err: any, accessToken?: string, refreshToken?: string, params?: any) => void): void;
_authorizeUrl: string;
_accessTokenUrl: string;
_clientId: string;
_clientSecret: string;
}
/**
* HTTP request object interface
*/
interface Request {
query?: { [key: string]: any };
body?: { [key: string]: any };
session?: { [key: string]: any };
app?: any;
headers?: { [key: string]: string };
connection?: { encrypted?: boolean };
url?: string;
}
/**
* State store interface
*/
interface StateStore {
store(req: Request, ...args: any[]): void;
verify(req: Request, providedState: string, callback: Function): void;
}
/**
* Error classes
*/
interface AuthorizationError extends Error {
name: 'AuthorizationError';
code: string;
uri?: string;
status: number;
}
interface TokenError extends Error {
name: 'TokenError';
code: string;
uri?: string;
status: number;
}
interface InternalOAuthError extends Error {
name: 'InternalOAuthError';
oauthError: any;
toString(): string;
}