Passport

repository·master·Indexed 12 days ago

https://github.com/jaredhanson/passport

Simple, unobtrusive authentication middleware for Node.js. Passport uses a pluggable 'strategy' system to support various authentication methods, such as Local, OAuth, and OpenID, without tying developers to a specific database or routing structure. Version 0.7.0 provides tools for session-based and stateless authentication, including serialization and deserialization for persistent login sessions.

Tokens
3.8K
Snippets
12
Records
15
Agent score
96%

What's inside Passport

  1. Configure persistent login sessions with serialization

    master

    To maintain persistent login sessions, you must implement serialization and deserialization logic. This allows Passport to store a minimal identifier (like a user ID) in the session and retrieve the full user object on subsequent requests.

    • passport.serializeUser: Defines how to store the user in the session.
    • passport.deserializeUser: Defines how to retrieve the user from the session using the stored identifier.
    passport.serializeUser(function(user, done) {
      done(null, user.id);
    });
    
    passport.deserializeUser(function(id, done) {
      User.findById(id, function (err, user) {
        done(err, user);
      });
    });
  2. How Passport strategies work

    master

    Passport uses strategies to authenticate requests. A strategy is a plugin that handles a specific authentication method, such as username/password (Local), OAuth (Facebook, Twitter), or OpenID.

    Before you can use a strategy, you must configure it using passport.use(). The strategy provides a callback function that receives credentials and a done function to signal success or failure to Passport.

    passport.use(new LocalStrategy(
      function(username, password, done) {
        User.findOne({ username: username }, function (err, user) {
          if (err) { return done(err); }
          if (!user) { return done(null, false); }
          if (!user.verifyPassword(password)) { return done(null, false); }
          return done(null, user);
        });
      }
    ));
  3. Integrate Passport middleware in Express

    master

    To use Passport in an Express or Connect-based application, you must include the passport.initialize() middleware. If you are using persistent sessions, you must also include passport.session() middleware.

    Note: passport.session() requires a session middleware (like express-session) to be configured before it.

    var app = express();
    app.use(require('serve-static')(__dirname + '/../../public'));
    app.use(require('cookie-parser')());
    app.use(require('body-parser').urlencoded({ extended: true }));
    app.use(require('express-session')({ secret: 'keyboard cat', resave: true, saveUninitialized: true }));
    app.use(passport.initialize());
    app.use(passport.session());
  4. Configure user serialization and deserialization

    master

    When using sessions with Passport, you must define how a user object is serialized into a session and how it is deserialized back from a session (typically via a database lookup using an ID).

    • passport.serializeUser(function(user, done) { ... }): Determines which data from the user object should be stored in the session (e.g., the user ID).
    • passport.deserializeUser(function(id, done) { ... }): Uses the stored data (e.g., the ID) to look up the full user object on subsequent requests.
    passport.serializeUser(function(user, done) {
      done(null, user.id);
    });
    
    passport.deserializeUser(function(id, done) {
      User.findById(id, function (err, user) {
        done(err, user);
      });
    });
  5. How Passport initialization and sessions work together

    master

    Passport operates in two modes depending on whether your application is stateless or session-based:

    1. Stateless Applications: If you are not using sessions, passport.initialize() is sufficient to attach authentication methods to the request, but it will not persist login state between requests.
    2. Session-based Applications: To persist login state, you must follow a specific middleware chain:
      • Session middleware (e.g., express-session or connect.session())
      • passport.initialize()
      • passport.session()

    In session-based mode, passport.serializeUser and passport.deserializeUser are required to bridge the gap between the session store and your user database.

  6. Authenticate requests using authenticate()

    master

    Use passport.authenticate() as route middleware to trigger the authentication process for a specific strategy. You can pass options like failureRedirect to specify where to send the user if authentication fails.

    app.post('/login', 
      passport.authenticate('local', { failureRedirect: '/login' }),
      function(req, res) {
        res.redirect('/');
      });
  7. Configure `passport.authenticate()` options

    master

    When calling passport.authenticate(name, options), you can pass an options object to customize the authentication behavior.

    OptionTypeDescription
    sessionBooleanWhether to save login state in the session. Defaults to true.
    successRedirectStringURL to redirect to after successful login.
    successMessageString/BooleanIf true, stores success message in req.session.messages. If a string, uses that string as the message.
    successFlashString/BooleanIf true, flashes success message. If a string, uses that string as the flash message (overrides strategy message).
    failureRedirectStringURL to redirect to after failed login.
    failureMessageString/BooleanIf true, stores failure message in req.session.messages. If a string, uses that string as the message.
    failureFlashString/BooleanIf true, flashes failure message. If a string, uses that string as the flash message (overrides strategy message).
    assignPropertyStringAssign the object provided by the verify callback to this specific property on the req object.
    failWithErrorBooleanIf true, authentication failures will trigger next() with an AuthenticationError instead of sending a response.
  8. Commonly used Passport strategies

    master

    Passport supports over 480 strategies. Below are some of the most common ones:

    |Strategy | Protocol | Developer |
    |---------------------------------------------------------------|--------------------------|------------------------------------------------|
    |[Local](https://github.com/jaredhanson/passport-local) | HTML form | [Jared Hanson](https://github.com/jaredhanson) |
    |[OpenID](https://github.com/jaredhanson/passport-openid) | OpenID | [Jared Hanson](https://github.com/jaredhanson) |
    |[BrowserID](https://github.com/jaredhanson/passport-browserid) | BrowserID | [Jared Hanson](https://github.com/jaredhanson) |
    |[Facebook](https://github.com/jaredhanson/passport-facebook) | OAuth 2.0 | [Jared Hanson](https://github.com/jaredhanson) |
    |[Google](https://github.com/jaredhanson/passport-google) | OpenID | [Jared Hanson](https://github.com/jaredhanson) |
    |[Google](https://github.com/jaredhanson/passport-google-oauth) | OAuth / OAuth 2.0 | [Jared Hanson](https://github.com/jaredhanson) |
    |[Twitter](https://github.com/jaredhanson/passport-twitter) | OAuth | [Jared Hanson](https://github.com/jaredhanson) |
    |[Azure Active Directory](https://github.com/AzureAD/passport-azure-ad) | OAuth 2.0 / OpenID / SAML | [Azure](https://github.com/azuread) |
  9. Handle AuthenticationError during authentication failures

    master
    When an authentication process fails, Passport may throw an AuthenticationError. This error is used to signal that the user could not be authenticated. It includes a message describing the failure and a status code, which defaults to 401 (Unauthorized) if not explicitly provided.
  10. Initialize Passport as a singleton

    master

    The passport module exports a pre-instantiated singleton instance of the Passport authenticator. For most standard use cases, you should require the module and use this exported instance directly to configure strategies and middleware.

    const passport = require('passport');
    
    // Use the singleton instance directly
    passport.use(new MyStrategy());
  11. Use `passport.authenticate()` middleware

    master

    The passport.authenticate() function is a middleware generator used to trigger authentication via a specific strategy or a chain of strategies.

    Default Behavior

    If no callback is provided, Passport handles the authentication flow automatically:

    • Success: The user is logged in, req.user is populated, and a session is established (if session: true). Depending on options, the user may be redirected.
    • Failure: An unauthorized response (typically 401) is sent, or the user is redirected to the failureRedirect URL.

    Using a Custom Callback

    If you provide a callback, you take responsibility for logging the user in, establishing a session, and handling redirects. The callback signature is: function(err, user, info, status)

    • err: An error object if an internal error occurred.
    • user: The authenticated user object on success, or false on failure.
    • info: Additional details provided by the strategy (e.g., profile info or a challenge message).
    • status: An optional HTTP status code (e.g., for remote authentication failures).

    Strategy Chaining

    You can pass an array of strategy names to authenticate(). Passport will attempt them in order. The first strategy to succeed, redirect, or error will halt the chain. This is useful for API endpoints supporting multiple authentication schemes (e.g., Basic, Digest, and Token).

    // Example 1: Default behavior with redirects
    passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' });
    
    // Example 2: API usage with session disabled
    passport.authenticate('basic', { session: false });
    
    // Example 3: Using a custom callback for manual control
    app.get('/protected', function(req, res, next) {
      passport.authenticate('local', function(err, user, info, status) {
        if (err) { return next(err); }
        if (!user) { return res.redirect('/signin'); }
        res.redirect('/account');
      })(req, res, next);
    });