or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

error-handling.mdindex.mdstate-management.md
tile.json

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.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/passport-oauth2@1.8.x

To install, run

npx @tessl/cli install tessl/npm-passport-oauth2@1.8.0

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