### Install passport-oauth2 using npm Source: https://github.com/jaredhanson/passport-oauth2/blob/master/README.md Installs the passport-oauth2 package from npm. This is the primary method for adding the OAuth 2.0 strategy to a Node.js project. ```bash $ npm install passport-oauth2 ``` -------------------------------- ### Express Route Configuration for OAuth2 Authentication Flow Source: https://context7.com/jaredhanson/passport-oauth2/llms.txt Configures Express routes to initiate OAuth2 authentication and handle the callback. Includes Passport initialization, session management, user serialization/deserialization, routes for initiating authentication and handling callbacks, and an example of a protected route. ```javascript const express = require('express'); const passport = require('passport'); const app = express(); // Initialize Passport and session support app.use(require('express-session')({ secret: 'keyboard cat', resave: false, saveUninitialized: false })); app.use(passport.initialize()); app.use(passport.session()); // Serialize user for session passport.serializeUser(function(user, done) { done(null, user.id); }); passport.deserializeUser(function(id, done) { User.findById(id, function(err, user) { done(err, user); }); }); // Route to initiate OAuth2 authentication app.get('/auth/provider', passport.authenticate('oauth2', { scope: ['profile', 'email'] }) ); // OAuth2 callback route app.get('/auth/callback', passport.authenticate('oauth2', { failureRedirect: '/login', failureMessage: true }), function(req, res) { // Successful authentication res.redirect('/dashboard'); } ); // Protected route example app.get('/dashboard', function(req, res, next) { if (!req.isAuthenticated()) { return res.redirect('/login'); } next(); }, function(req, res) { res.json({ user: req.user }); } ); app.listen(3000); ``` -------------------------------- ### Subclass OAuth2Strategy for Custom Provider in JavaScript Source: https://context7.com/jaredhanson/passport-oauth2/llms.txt This example demonstrates subclassing the Passport OAuth2Strategy to create a provider-specific strategy. It customizes authorization and token URLs, scope separators, and overrides the `userProfile` method to fetch user data from a custom endpoint. It also customizes parameters for authorization and token requests. ```javascript const OAuth2Strategy = require('passport-oauth2'); const util = require('util'); // Custom provider strategy function CustomProviderStrategy(options, verify) { options = options || {}; options.authorizationURL = options.authorizationURL || 'https://custom-provider.com/oauth/authorize'; options.tokenURL = options.tokenURL || 'https://custom-provider.com/oauth/token'; options.scopeSeparator = options.scopeSeparator || ','; OAuth2Strategy.call(this, options, verify); this.name = 'custom-provider'; this._userProfileURL = options.userProfileURL || 'https://custom-provider.com/api/user'; } // Inherit from OAuth2Strategy util.inherits(CustomProviderStrategy, OAuth2Strategy); // Override userProfile to fetch user data from provider CustomProviderStrategy.prototype.userProfile = function(accessToken, done) { this._oauth2.get(this._userProfileURL, accessToken, function(err, body, res) { if (err) { return done(new OAuth2Strategy.InternalOAuthError('Failed to fetch user profile', err)); } try { const json = JSON.parse(body); const profile = { provider: 'custom-provider', id: json.id, displayName: json.name, username: json.username, emails: [{ value: json.email }], photos: [{ value: json.avatar_url }], _raw: body, _json: json }; done(null, profile); } catch (e) { done(e); } }); }; // Override authorizationParams to add custom parameters CustomProviderStrategy.prototype.authorizationParams = function(options) { return { access_type: 'offline', prompt: 'consent' }; }; // Override tokenParams for custom token request parameters CustomProviderStrategy.prototype.tokenParams = function(options) { return { grant_type: 'authorization_code' }; }; // Use the custom strategy passport.use(new CustomProviderStrategy({ clientID: 'custom-client-id', clientSecret: 'custom-client-secret', callbackURL: 'http://localhost:3000/auth/custom/callback', scope: ['user:email', 'user:profile'] }, function(accessToken, refreshToken, profile, done) { User.findOrCreate({ customId: profile.id }, function(err, user) { return done(err, user); }); } )); ``` -------------------------------- ### OAuth2 Strategy with PKCE Support Initialization Source: https://context7.com/jaredhanson/passport-oauth2/llms.txt Enables PKCE (Proof Key for Code Exchange) for enhanced security, especially for public clients. This method requires 'state: true' and specifies the PKCE transformation method (e.g., 'S256'). The verify callback handles access tokens and user lookup or creation. ```javascript const OAuth2Strategy = require('passport-oauth2'); // OAuth2 strategy with PKCE enabled passport.use('oauth2-pkce', new OAuth2Strategy({ authorizationURL: 'https://secure-provider.example.com/oauth2/authorize', tokenURL: 'https://secure-provider.example.com/oauth2/token', clientID: 'your-client-id', clientSecret: 'your-client-secret', callbackURL: 'http://localhost:3000/auth/callback', state: true, // Required when PKCE is enabled pkce: 'S256', // Use S256 transformation method (or 'plain') scope: ['openid', 'profile'] }, function(accessToken, refreshToken, profile, done) { console.log('Access token:', accessToken); User.findByProviderId(profile.id, function(err, user) { if (err) return done(err); if (!user) { user = new User({ providerId: profile.id, accessToken: accessToken, refreshToken: refreshToken }); user.save(function(err) { return done(err, user); }); } else { return done(null, user); } }); } )); ``` -------------------------------- ### Basic OAuth2 Strategy Initialization with Passport.js Source: https://context7.com/jaredhanson/passport-oauth2/llms.txt Initializes a new OAuth2Strategy instance for Passport.js, requiring configuration for authorization and token endpoints, client credentials, callback URL, scope, and a verify callback function to process the authenticated user. ```javascript const OAuth2Strategy = require('passport-oauth2'); const passport = require('passport'); // Basic OAuth2 strategy configuration passport.use(new OAuth2Strategy({ authorizationURL: 'https://provider.example.com/oauth2/authorize', tokenURL: 'https://provider.example.com/oauth2/token', clientID: 'your-client-id', clientSecret: 'your-client-secret', callbackURL: 'http://localhost:3000/auth/callback', scope: ['profile', 'email'] }, function(accessToken, refreshToken, profile, done) { // Verify callback - find or create user in your database User.findOrCreate({ providerId: profile.id }, function (err, user) { if (err) { return done(err); } return done(null, user); }); } )); ``` -------------------------------- ### Run Test Suite Source: https://github.com/jaredhanson/passport-oauth2/blob/master/README.md Executes the complete test suite for the passport-oauth2 module using make. This is crucial for verifying code changes and ensuring the library functions as expected. ```bash $ make test ``` -------------------------------- ### Dynamic OAuth2 Callback URL Configuration (Node.js) Source: https://context7.com/jaredhanson/passport-oauth2/llms.txt Shows how to dynamically configure the callback URL for the OAuth2Strategy based on the incoming request. This is particularly useful for applications that need to support multiple domains or varying hostnames, such as in multi-tenant or complex development environments. ```javascript const OAuth2Strategy = require('passport-oauth2'); passport.use(new OAuth2Strategy({ authorizationURL: 'https://provider.example.com/oauth2/authorize', tokenURL: 'https://provider.example.com/oauth2/token', clientID: 'your-client-id', clientSecret: 'your-client-secret', callbackURL: '/auth/callback', // Relative URL proxy: true // Trust proxy headers for protocol detection }, function(accessToken, refreshToken, profile, done) { return done(null, profile); } )); // Initiate auth with dynamic callback app.get('/auth/provider', function(req, res, next) { // Determine callback URL based on request const protocol = req.secure ? 'https' : 'http'; const host = req.get('host'); const callbackURL = `${protocol}://${host}/auth/callback`; passport.authenticate('oauth2', { callbackURL: callbackURL, state: req.query.returnTo || '/' })(req, res, next); }); // Handle callback app.get('/auth/callback', passport.authenticate('oauth2', { failureRedirect: '/login' }), function(req, res) { // Redirect to original destination from state const returnTo = req.session.returnTo || '/'; delete req.session.returnTo; res.redirect(returnTo); } ); ``` -------------------------------- ### Implement Custom OAuth2 State Store in JavaScript Source: https://context7.com/jaredhanson/passport-oauth2/llms.txt This implementation provides a custom state store for OAuth2, handling the generation, storage, and verification of state tokens to mitigate CSRF attacks. It relies on the 'uid2' module for token generation. The store manages state data including verifier, state, metadata, and timestamps, with a 5-minute expiration for state tokens. ```javascript const OAuth2Strategy = require('passport-oauth2'); // Custom state store implementation function CustomStateStore() { this.store = {}; } CustomStateStore.prototype.store = function(req, verifier, state, meta, callback) { // Generate state token const stateToken = require('uid2')(24); // Store state data with metadata this.store[stateToken] = { verifier: verifier, state: state, meta: meta, timestamp: Date.now() }; // Return state token to be sent to provider callback(null, stateToken); }; CustomStateStore.prototype.verify = function(req, stateToken, meta, callback) { const stateData = this.store[stateToken]; if (!stateData) { return callback(null, false, { message: 'Invalid state token' }); } // Verify state hasn't expired (5 minutes) if (Date.now() - stateData.timestamp > 300000) { delete this.store[stateToken]; return callback(null, false, { message: 'State token expired' }); } // Clean up used state delete this.store[stateToken]; // Return verifier for PKCE or true for standard flow callback(null, stateData.verifier || true, stateData.state); }; // Use custom state store passport.use(new OAuth2Strategy({ authorizationURL: 'https://provider.example.com/oauth2/authorize', tokenURL: 'https://provider.example.com/oauth2/token', clientID: 'your-client-id', clientSecret: 'your-client-secret', callbackURL: 'http://localhost:3000/auth/callback', store: new CustomStateStore(), pkce: true, state: true }, function(accessToken, refreshToken, profile, done) { return done(null, profile); } )); ``` -------------------------------- ### Generate and View Test Coverage Reports Source: https://github.com/jaredhanson/passport-oauth2/blob/master/README.md Generates and displays test coverage reports for the passport-oauth2 module. This helps identify areas of the code that are not adequately tested, encouraging the writing of more comprehensive tests. ```bash $ make test-cov $ make view-cov ``` -------------------------------- ### Configure Passport-OAuth2 to Skip User Profile Source: https://context7.com/jaredhanson/passport-oauth2/llms.txt This configuration tells the OAuth2Strategy to skip fetching user profile information. This is useful when only access tokens are required, reducing unnecessary API calls and improving performance. The profile parameter in the verification callback will be undefined. ```javascript const OAuth2Strategy = require('passport-oauth2'); passport.use(new OAuth2Strategy({ authorizationURL: 'https://provider.example.com/oauth2/authorize', tokenURL: 'https://provider.example.com/oauth2/token', clientID: 'your-client-id', clientSecret: 'your-client-secret', callbackURL: 'http://localhost:3000/auth/callback', skipUserProfile: true // Don't fetch user profile }, function(accessToken, refreshToken, profile, done) { // profile will be undefined when skipUserProfile is true // Store just the tokens const tokenData = { accessToken: accessToken, refreshToken: refreshToken, provider: 'oauth2' }; // Create or update user record with tokens User.findOrCreateByToken(accessToken, function(err, user) { if (err) return done(err); user.accessToken = accessToken; user.refreshToken = refreshToken; user.save(function(saveErr) { done(saveErr, user); }); }); } )); ``` -------------------------------- ### Access Request Object in OAuth2 Verify Callback (Node.js) Source: https://context7.com/jaredhanson/passport-oauth2/llms.txt Demonstrates how to enable and access the Express request object within the `verify` callback of the OAuth2Strategy. This is useful for multi-tenant applications or when authentication logic requires request-specific data like IP addresses, headers, or session information. ```javascript const OAuth2Strategy = require('passport-oauth2'); passport.use(new OAuth2Strategy({ authorizationURL: 'https://provider.example.com/oauth2/authorize', tokenURL: 'https://provider.example.com/oauth2/token', clientID: 'your-client-id', clientSecret: 'your-client-secret', callbackURL: 'http://localhost:3000/auth/callback', passReqToCallback: true // Enable request in verify callback }, function(req, accessToken, refreshToken, profile, done) { // Access request data in verify callback const ipAddress = req.ip; const userAgent = req.headers['user-agent']; const sessionId = req.sessionID; // Use request context for authentication logic User.findOrCreate({ providerId: profile.id }, function(err, user) { if (err) return done(err); // Log authentication event with context AuthLog.create({ userId: user.id, ipAddress: ipAddress, userAgent: userAgent, sessionId: sessionId, timestamp: new Date() }, function(logErr) { if (logErr) console.error('Failed to log auth event:', logErr); done(null, user); }); }); } )); ``` -------------------------------- ### Configure OAuth2Strategy with passport.js Source: https://github.com/jaredhanson/passport-oauth2/blob/master/README.md Configures the OAuth2Strategy for Passport.js by specifying authorization and token URLs, client ID and secret, and a callback URL. It includes a verify callback to handle user lookup or creation after successful authentication. ```javascript passport.use(new OAuth2Strategy({ authorizationURL: 'https://www.example.com/oauth2/authorize', tokenURL: 'https://www.example.com/oauth2/token', clientID: EXAMPLE_CLIENT_ID, clientSecret: EXAMPLE_CLIENT_SECRET, callbackURL: "http://localhost:3000/auth/example/callback" }, function(accessToken, refreshToken, profile, cb) { User.findOrCreate({ exampleId: profile.id }, function (err, user) { return cb(err, user); }); } )); ``` -------------------------------- ### OAuth2 Error Handling with Passport (Node.js) Source: https://context7.com/jaredhanson/passport-oauth2/llms.txt Illustrates how to handle various OAuth2-specific errors, including authorization errors, token errors, and internal OAuth errors, within an Express application using passport-oauth2. It shows setting up the strategy and then defining custom error handling middleware. ```javascript const OAuth2Strategy = require('passport-oauth2'); const { AuthorizationError, TokenError, InternalOAuthError } = require('passport-oauth2'); passport.use(new OAuth2Strategy({ authorizationURL: 'https://provider.example.com/oauth2/authorize', tokenURL: 'https://provider.example.com/oauth2/token', clientID: 'your-client-id', clientSecret: 'your-client-secret', callbackURL: 'http://localhost:3000/auth/callback' }, function(accessToken, refreshToken, profile, done) { User.findOrCreate({ providerId: profile.id }, function(err, user) { return done(err, user); }); } )); // Error handling in Express app.get('/auth/callback', passport.authenticate('oauth2', { failureRedirect: '/login', failureFlash: true }), function(req, res) { res.redirect('/dashboard'); } ); // Custom error handler app.use(function(err, req, res, next) { if (err instanceof AuthorizationError) { // Handle authorization errors (user denied access, etc.) console.error('Authorization error:', { code: err.code, message: err.message, uri: err.uri, status: err.status }); res.status(err.status || 403).render('auth-error', { message: 'Authorization failed: ' + err.message }); } else if (err instanceof TokenError) { // Handle token exchange errors console.error('Token error:', { code: err.code, message: err.message }); res.status(err.status || 500).render('auth-error', { message: 'Token exchange failed' }); } else if (err instanceof InternalOAuthError) { // Handle internal OAuth errors console.error('Internal OAuth error:', err.toString()); res.status(500).render('auth-error', { message: 'Authentication service error' }); } else { next(err); } }); ``` -------------------------------- ### Authenticate Requests with OAuth2 Strategy in Express Source: https://github.com/jaredhanson/passport-oauth2/blob/master/README.md Sets up Express routes to handle OAuth 2.0 authentication flow. The first route initiates the authentication process, and the second handles the callback from the OAuth provider, including error handling and redirection upon success. ```javascript app.get('/auth/example', passport.authenticate('oauth2')); app.get('/auth/example/callback', passport.authenticate('oauth2', { failureRedirect: '/login' }), function(req, res) { // Successful authentication, redirect home. res.redirect('/'); }); ``` -------------------------------- ### Conditional Skip User Profile with Passport-OAuth2 Source: https://context7.com/jaredhanson/passport-oauth2/llms.txt This advanced configuration allows for a dynamic decision on whether to skip user profile retrieval. The `skipUserProfile` option accepts a function that performs an asynchronous check (e.g., against a cache) to determine if the profile should be fetched. ```javascript // Conditional skip based on logic passport.use('oauth2-conditional', new OAuth2Strategy({ authorizationURL: 'https://provider.example.com/oauth2/authorize', tokenURL: 'https://provider.example.com/oauth2/token', clientID: 'your-client-id', clientSecret: 'your-client-secret', callbackURL: 'http://localhost:3000/auth/callback', skipUserProfile: function(accessToken, done) { // Async decision to skip profile TokenCache.exists(accessToken, function(err, exists) { if (err) return done(err); // Skip if we already have the profile cached done(null, exists); }); } }, function(accessToken, refreshToken, profile, done) { return done(null, { accessToken, refreshToken, profile }); } )); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.