brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
passport-jsPassport.js is authentication middleware for Express and other Node.js frameworks, with strategies for local passwords, Google, GitHub and many other providers. Use when implementing login with Google/GitHub/email, OAuth, session auth, or social login.
Independent GitHub snapshot · Automated classification · Original documentation governs
Passport.js is Express-compatible authentication middleware with 480+ strategies (Google, GitHub, Facebook, SAML, LDAP, local). Login state is kept in a session by default; stateless JWT strategies exist too. Checked against passport 0.7.0, passport-local 1.0.0, passport-google-oauth20 2.0.0 and Express 5.
npm install express express-session passport passport-local passport-google-oauth20 bcrypt
npm install --save-dev @types/passport @types/passport-local @types/passport-google-oauth20 @types/express-session
import express from 'express'
import session from 'express-session'
import passport from 'passport'
const app = express()
app.use(express.urlencoded({ extended: false }))
app.use(session({
secret: process.env.SESSION_SECRET!,
resave: false,
saveUninitialized: false,
cookie: { httpOnly: true, sameSite: 'lax', secure: process.env.NODE_ENV === 'production' },
}))
app.use(passport.authenticate('session'))
Behind a reverse proxy also set app.set('trust proxy', 1), otherwise secure cookies and the OAuth callback URL break.
import passport from 'passport'
import { Strategy as LocalStrategy } from 'passport-local'
import bcrypt from 'bcrypt'
passport.use(new LocalStrategy(
{ usernameField: 'email' },
async (email, password, done) => {
const user = await db.users.findByEmail(email)
if (!user) return done(null, false, { message: 'No account' })
if (!await bcrypt.compare(password, user.passwordHash)) return done(null, false)
return done(null, user)
}
))
passport.serializeUser((user: any, cb) => process.nextTick(() => cb(null, user.id)))
passport.deserializeUser((id: string, cb) => {
db.users.findById(id).then((user) => cb(null, user), cb)
})
import { Strategy as GoogleStrategy } from 'passport-google-oauth20'
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
callbackURL: '/auth/google/callback', // must match the authorized redirect URI in the Google console
}, async (accessToken, refreshToken, profile, done) => {
let user = await db.users.findByOAuthId('google', profile.id)
if (!user) user = await db.users.create({
email: profile.emails?.[0]?.value, // may be undefined; handle it
name: profile.displayName,
oauthProvider: 'google', oauthId: profile.id,
})
return done(null, user)
}))
app.post('/login', passport.authenticate('local', {
successRedirect: '/dashboard', failureRedirect: '/login',
}))
app.get('/auth/google', passport.authenticate('google', { scope: ['profile', 'email'] }))
app.get('/auth/google/callback', passport.authenticate('google', {
successRedirect: '/dashboard', failureRedirect: '/login',
}))
// Passport 0.6+ needs a callback, and logout should be POST
app.post('/logout', (req, res, next) => {
req.logout((err) => (err ? next(err) : res.redirect('/')))
})
// Protect pages
const requireLogin = (req, res, next) => (req.isAuthenticated() ? next() : res.redirect('/login'))
app.get('/dashboard', requireLogin, (req, res) => res.send(`Hello ${req.user.name}`))
For GitHub use passport-github2; other strategies are listed at passportjs.org.
Request: "Add email and password login to my Express app."
Install the packages in Step 1, add the local strategy and POST /login. Posting email=maria@northwind.dev&password=... with a correct password answers 302 Location: /dashboard and sets a session cookie; GET /dashboard then returns the page, and after POST /logout it redirects to /login.
Request: "Let users sign in with Google."
Create an OAuth client in the Google Cloud console, put the client ID and secret in GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET, and add the Step 3 strategy. GET /auth/google answers 302 to https://accounts.google.com/o/oauth2/v2/auth?....
req.logout() requires a callback; old snippets that call it without one fail.SESSION_SECRET and OAuth secrets from the environment, never from source.