Koa Passport Authentication Middleware

6.0.0 · active · verified Wed Apr 22

koa-passport is a middleware that integrates the popular Passport.js authentication library with the Koa web framework. It simplifies the process of adding various authentication strategies (like local username/password, OAuth, JWT) to Koa applications by exposing Passport's core functionalities directly on the Koa `ctx` object. The current stable version is 6.x, which is designed to work with Koa 2.x and Passport.js 5.x or 6.x. Its release cadence is closely tied to the major versions of its upstream `passport` and `koa` dependencies, ensuring compatibility. Key differentiators include its idiomatic Koa middleware interface, providing `ctx.login()`, `ctx.logout()`, `ctx.isAuthenticated()`, and `ctx.isUnauthenticated()` methods, which streamline user session management and status checks within Koa's async context. It requires external session management middleware like `koa-session` and typically a body parser for credential submission.

Common errors

Warnings

Install

Imports

Quickstart

This example sets up a basic Koa application with `koa-passport` using a local authentication strategy. It demonstrates session management, body parsing, user serialization/deserialization, and defines routes for login, logout, and a protected profile page. It also includes a basic HTML login form.

const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const session = require('koa-session');
const passport = require('koa-passport');
const LocalStrategy = require('passport-local').Strategy;

const app = new Koa();

// Session Configuration
app.keys = ['your-secret-key']; // Replace with a strong, random key in production
app.use(session({}, app));

// Body Parser
app.use(bodyParser());

// Passport Initialization
app.use(passport.initialize());
app.use(passport.session());

// Define a local authentication strategy
passport.use(new LocalStrategy(
  function(username, password, done) {
    // Simulate user lookup
    if (username === 'test' && password === 'password') {
      return done(null, { id: 1, username: 'test' });
    } else {
      return done(null, false);
    }
  }
));

// Serialize and Deserialize user for session management
passport.serializeUser(function(user, done) {
  done(null, user.id);
});

passport.deserializeUser(function(id, done) {
  // Simulate user lookup by ID
  done(null, { id: id, username: 'test' });
});

// Routes
app.use(async ctx => {
  if (ctx.path === '/login' && ctx.method === 'POST') {
    return passport.authenticate('local', async (err, user, info, status) => {
      if (user) {
        await ctx.login(user);
        ctx.body = `Hello, ${user.username}! You are logged in.`;
      } else {
        ctx.status = 401;
        ctx.body = 'Login failed.';
      }
    })(ctx);
  } else if (ctx.path === '/logout') {
    ctx.logout();
    ctx.redirect('/');
  } else if (ctx.path === '/profile') {
    if (ctx.isAuthenticated()) {
      ctx.body = `Welcome back, ${ctx.state.user.username}!`;
    } else {
      ctx.redirect('/login-page'); // Redirect to a login page
    }
  } else if (ctx.path === '/login-page') {
    ctx.body = `
      <h1>Login</h1>
      <form action="/login" method="post">
        <input type="text" name="username" placeholder="username" />
        <input type="password" name="password" placeholder="password" />
        <button type="submit">Login</button>
      </form>
    `;
  } else {
    ctx.body = `
      <h1>Home</h1>
      <p>Status: ${ctx.isAuthenticated() ? 'Logged In' : 'Logged Out'}</p>
      <p><a href="/login-page">Login</a></p>
      <p><a href="/profile">Profile</a></p>
      ${ctx.isAuthenticated() ? '<p><a href="/logout">Logout</a></p>' : ''}
    `;
  }
});

app.listen(3000, () => console.log('Server running on http://localhost:3000'));

view raw JSON →