CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-passport-oauth2

OAuth 2.0 authentication strategy for Passport that enables developers to implement OAuth 2.0-based authentication in Node.js applications.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

index.mddocs/

Passport OAuth2

General-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.

Package Information

  • Package Name: passport-oauth2
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install passport-oauth2

Core Imports

// 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';

Basic Usage

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('/');
  });

Architecture

Passport OAuth2 is built around several key components:

  • OAuth2Strategy: Core strategy class that extends passport.Strategy and handles the OAuth 2.0 flow
  • Error Classes: Specialized error types for different OAuth 2.0 failure scenarios
  • State Management: Multiple state store implementations for CSRF protection and PKCE support
  • Extensibility: Virtual methods that can be overridden for provider-specific behavior
  • Verification Callback: User-defined function that handles user creation/authentication after successful OAuth flow

Capabilities

OAuth2 Strategy

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;

Strategy Methods

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);

Error Handling

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);

Error Handling

State Management

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
}

State Management

Utility Functions

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
}

Types

/**
 * 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;
}

docs

error-handling.md

index.md

state-management.md

tile.json