Introduction to koa-passport
koa-passport is an authentication middleware for Koa.js, which is a modern, scalable framework for building web applications. koa-passport integrates smoothly with any Koa application and provides a wide variety of authentication strategies to help you secure your applications.
API Examples
Basic Setup
const Koa = require('koa'); const bodyParser = require('koa-bodyparser'); const session = require('koa-session'); const passport = require('koa-passport'); const app = new Koa(); app.keys = ['secret-key']; app.use(session(app)); app.use(bodyParser()); app.use(passport.initialize()); app.use(passport.session()); app.listen(3000); console.log('Server running on http://localhost:3000');
Serialization
passport.serializeUser((user, done) => { done(null, user.id); }); passport.deserializeUser((id, done) => { // Assuming User is a model representing users in your DB User.findById(id, (err, user) => { done(err, user); }); });
Local Strategy
const LocalStrategy = require('passport-local').Strategy; passport.use(new LocalStrategy((username, password, done) => { // Assuming User is a model representing users in your DB User.findOne({ username: username }, (err, user) => { if (err) { return done(err); } if (!user) { return done(null, false, { message: 'Incorrect username.' }); } if (!user.validPassword(password)) { return done(null, false, { message: 'Incorrect password.' }); } return done(null, user); }); }));
Routes
const Router = require('koa-router'); const router = new Router(); router.get('/login', async (ctx) => { await ctx.render('login'); // Assuming you are using a templating engine }); router.post('/login', passport.authenticate('local', { successRedirect: '/profile', failureRedirect: '/login' }) ); app.use(router.routes()).use(router.allowedMethods());
Google OAuth Strategy
const GoogleStrategy = require('passport-google-oauth').OAuth2Strategy; passport.use(new GoogleStrategy({ clientID: 'GOOGLE_CLIENT_ID', clientSecret: 'GOOGLE_CLIENT_SECRET', callbackURL: 'http://localhost:3000/auth/google/callback' }, (token, tokenSecret, profile, done) => { // Assuming User is a model representing users in your DB User.findOne({ googleId: profile.id }, (err, user) => { return done(err, user); }); })); router.get('/auth/google', passport.authenticate('google', { scope: ['https://www.googleapis.com/auth/plus.login'] }) ); router.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/login' }), (ctx) => { ctx.redirect('/profile'); });
Protected Routes
function ensureAuthenticated(ctx, next) { if (ctx.isAuthenticated()) { return next(); } else { ctx.redirect('/login'); } } router.get('/profile', ensureAuthenticated, async (ctx) => { await ctx.render('profile', { user: ctx.state.user }); });
Example Application
const Koa = require('koa'); const bodyParser = require('koa-bodyparser'); const session = require('koa-session'); const passport = require('koa-passport'); const Router = require('koa-router'); const LocalStrategy = require('passport-local').Strategy; const app = new Koa(); const router = new Router(); app.keys = ['secret-key']; app.use(session(app)); app.use(bodyParser()); app.use(passport.initialize()); app.use(passport.session()); // User model stub const users = [ { id: 1, username: 'testUser', password: 'testPassword' } ]; const User = { findOne: ({ username }) => users.find(user => user.username === username), findById: (id) => users.find(user => user.id === id), validPassword: (password) => users[0].password === password }; passport.serializeUser((user, done) => done(null, user.id)); passport.deserializeUser((id, done) => done(null, User.findById(id))); passport.use(new LocalStrategy((username, password, done) => { const user = User.findOne({ username }); if (!user) return done(null, false, { message: 'Incorrect username.' }); if (!user.validPassword(password)) return done(null, false, { message: 'Incorrect password.' }); return done(null, user); })); router.get('/login', async (ctx) => { ctx.body = ''; }); router.post('/login', passport.authenticate('local', { successRedirect: '/profile', failureRedirect: '/login' })); function ensureAuthenticated(ctx, next) { if (ctx.isAuthenticated()) return next(); ctx.redirect('/login'); } router.get('/profile', ensureAuthenticated, async (ctx) => { ctx.body = `
Hello ${ctx.state.user.username}
`; }); app.use(router.routes()).use(router.allowedMethods()); app.listen(3000, () => console.log('Server running on http://localhost:3000'));Hash: 0af30059afb9c999ffd46e8ea9969b45e8ab236a395e0a27b3c28aa12382f142