passport-oauth2
A generic OAuth 2.0 authentication strategy for Passport, the base class most provider-specific Passport login strategies are built on.
Repository Health
Technical Analysis
passport-oauth2 implements the OAuth 2.0 authorization code flow as a Passport.js authentication strategy, letting a Node application delegate login to any OAuth 2.0-compliant provider. Rather than shipping provider-specific logic, it exposes the generic pieces of the flow — authorization redirect, code exchange, state verification, and profile loading — as overridable methods, which is why the vast majority of provider strategies in the Passport ecosystem (Google, GitHub, Facebook, and hundreds of others) subclass it instead of reimplementing OAuth 2.0 from scratch.
Beyond the base flow, the library handles CSRF-style state verification through pluggable state stores (session-based, PKCE-aware, or custom), supports the OAuth 2.0 Form Post response mode, and normalizes error handling for both authorization errors and token-endpoint failures. Applications typically don’t use it directly; they either pick a provider-specific strategy that extends it, or subclass it themselves when adding support for a provider that doesn’t already have one.
What You Get
- An
OAuth2Strategyclass implementing the full authorization code grant: redirect to the provider, handle the callback, exchange the code for tokens, and invoke a verify callback with the resulting user profile. - Pluggable state stores —
NullStore(no state), a session-basedSessionStore/StateStorepair, and a PKCE-awarePKCEStateStore— for CSRF protection during the OAuth handshake. - Built-in support for PKCE (
plainandS256code challenge methods), enabled via a singlepkceoption. - Overridable protected methods (
userProfile,authorizationParams,tokenParams,parseErrorResponse) that subclass strategies use to add provider-specific behavior without touching the core flow. - Typed error classes (
AuthorizationError,TokenError,InternalOAuthError) that surface RFC 6749-style error responses from the provider in a structured way. - Support for the OAuth 2.0 Form Post response mode, so authorization responses delivered as HTML form POSTs (instead of query strings) are handled the same way.
Common Use Cases
- Serving as the parent class for a provider-specific Passport strategy (e.g.
passport-google-oauth20,passport-github2) instead of reimplementing the OAuth 2.0 flow. - Adding “Sign in with X” support for an OAuth 2.0 provider that has no existing Passport strategy, by subclassing
OAuth2Strategyand overridinguserProfile. - Wiring session-backed CSRF state protection into a login flow via the
state: trueoption and the default session state store. - Enabling PKCE for public or SPA-adjacent OAuth clients that can’t safely hold a client secret.
Under The Hood
Architecture
The library is a single OAuth2Strategy constructor (lib/strategy.js) that inherits from passport-strategy via util.inherits, with authenticate(req, options) as the sole entry point Passport calls per request. That method branches on whether the request carries an authorization code (callback leg) or not (initial redirect leg), delegating state persistence and verification to an injected state-store object (lib/state/{null,session,store,pkcesession}.js) selected at construction time based on the state, store, and pkce options — a simple strategy pattern that lets CSRF/PKCE handling vary without touching the core flow. Token exchange itself is delegated to the oauth package’s OAuth2 client held as this._oauth2, and profile loading, parameter injection, and error parsing are all exposed as overridable prototype methods (userProfile, authorizationParams, tokenParams, parseErrorResponse) — the whole design exists to be subclassed, not used standalone, which is reflected in lib/index.js exporting the strategy plus its error classes as the module’s public surface.
Tech Stack
Written in pre-ES6 CommonJS JavaScript (var, util.inherits) targeting Node >= 0.4, reflecting its age. Runtime dependencies are minimal and narrowly scoped: oauth for the actual HTTP token exchange, passport-strategy for the base Strategy class contract, uid2 for random state handles, base64url and Node’s built-in crypto for PKCE code verifier/challenge generation, and utils-merge for shallow object merging. There’s no build step — main points straight at ./lib — and the dev toolchain is equally old-school: mocha 2.x with chai/chai-passport-strategy for assertions and proxyquire for dependency stubbing, run via a Makefile and Travis CI config rather than a modern npm-scripts/GitHub Actions setup.
Code Quality
Test coverage is extensive relative to the codebase’s size — the test/ directory has one spec file per concern (base strategy, PKCE, form-post mode, session state, custom state stores, subclassing, profile loading, error types) plus a shared bootstrap, and chai-passport-strategy gives the specs a declarative way to assert on success/fail/redirect/error outcomes without spinning up real HTTP. Error handling is explicit and typed (AuthorizationError, TokenError, InternalOAuthError all extend Error with named subtypes) rather than swallowed, and verify-callback arity is introspected at runtime to support multiple call signatures. There are no TypeScript types, no linter config beyond a bare .jshintrc, and no CI badge activity beyond the legacy Travis config, consistent with a mature, low-churn package rather than an actively modernized one.
API Design
The public surface is intentionally tiny — a single constructor plus three exported error classes — which keeps the barrier to first use low: pass authorizationURL, tokenURL, clientID, clientSecret, and a verify callback, and passport.authenticate('oauth2') works. Extension points are equally minimal (four protected methods to override), and options like pkce: true or state: true toggle meaningful behavior with a single boolean rather than requiring separate configuration objects. The tradeoff is that the base strategy provides no user-profile fetching at all (userProfile is a no-op returning {}), so any real integration requires either a provider-specific subclass or writing one — appropriate for a base class, but not usable standalone without that extra step.
Used by 10 apps in this directory
Blinko
Knowledge Management · Note Taking
A self-hosted, AI-powered card note-taking tool that lets you capture fleeting thoughts instantly and retrieve them with natural language search.
Infisical
Security · Devops
The open-source platform for secrets, certificates, privileged access, and AI agent security — all in one self-hostable system.
Lightdash
Analytics · Data Engineering
The open-source Looker alternative that turns your dbt project's metrics and dimensions into governed, self-serve charts and dashboards — no license key required.
Novu
Developer Tools
Open-source communication infrastructure that connects your products and AI agents to every channel your users live on — Inbox, Email, SMS, Push, Chat, and more.
Outline
Knowledge Management · Collaboration
A fast, real-time collaborative knowledge base for growing teams built on React, Node.js, and ProseMirror.
overleaf
Collaboration · Productivity
Open-source, real-time collaborative LaTeX editor with sandboxed compilation and full TeXLive support for self-hosted academic and research teams.
Plasmic
CMS · Low Code Platforms · No Code Platforms
The open-source visual builder that lets teams design React apps and websites with drag-and-drop while integrating seamlessly with your codebase.
Refly
No Code Platforms · AI Development · Automation
Build deterministic, versioned agent skills from natural language—run them anywhere from Claude Code to Slack.
Rocket.Chat
Team Chat
The secure, self-hosted team communications platform for organizations that cannot compromise on data sovereignty.