Skip to content
Plurafy

Authentication and JWT

Implementing authentication with JWT tokens

Securely authenticate users and maintain sessions using JWT tokens.

JWT (JSON Web Tokens) provide a stateless way to authenticate requests without server-side sessions.

const jwt = require('jsonwebtoken');
const secret = 'your-secret-key';
// Create token
const token = jwt.sign(
{ userId: 123, email: 'user@example.com' },
secret,
{ expiresIn: '24h' }
);
console.log(token);
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
// Verify token
try {
const decoded = jwt.verify(token, secret);
console.log('Valid token:', decoded);
} catch (error) {
console.error('Invalid token:', error.message);
}
const express = require('express');
const app = express();
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
jwt.verify(token, secret, (error, user) => {
if (error) {
return res.status(403).json({ error: 'Invalid token' });
}
req.user = user;
next();
});
}
// Protected route
app.get('/protected', authenticateToken, (req, res) => {
res.json({ message: 'Secret data', user: req.user });
});
// Login route
app.post('/login', (req, res) => {
// Verify username/password
const user = { userId: 123, email: 'user@example.com' };
const token = jwt.sign(user, secret, { expiresIn: '24h' });
res.json({ token });
});
// Access token (short-lived) + Refresh token (long-lived)
let refreshTokens = [];
app.post('/login', (req, res) => {
const user = { userId: 123, email: 'user@example.com' };
const accessToken = jwt.sign(user, secret, { expiresIn: '15m' });
const refreshToken = jwt.sign(user, secret, { expiresIn: '7d' });
refreshTokens.push(refreshToken);
res.json({ accessToken, refreshToken });
});
app.post('/refresh', (req, res) => {
const { refreshToken } = req.body;
if (!refreshTokens.includes(refreshToken)) {
return res.status(401).json({ error: 'Invalid refresh token' });
}
jwt.verify(refreshToken, secret, (error, user) => {
if (error) {
return res.status(403).json({ error: 'Refresh token expired' });
}
const newAccessToken = jwt.sign(
{ userId: user.userId, email: user.email },
secret,
{ expiresIn: '15m' }
);
res.json({ accessToken: newAccessToken });
});
});
app.post('/logout', (req, res) => {
const { refreshToken } = req.body;
refreshTokens = refreshTokens.filter(t => t !== refreshToken);
res.json({ message: 'Logged out' });
});
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: '/auth/google/callback'
}, (accessToken, refreshToken, profile, done) => {
// Find or create user
User.findOrCreate({ googleId: profile.id }, (error, user) => {
return done(error, user);
});
}));
app.get('/auth/google',
passport.authenticate('google', { scope: ['email'] })
);
app.get('/auth/google/callback',
passport.authenticate('google', { failureRedirect: '/login' }),
(req, res) => {
const token = jwt.sign(
{ userId: req.user.id },
secret,
{ expiresIn: '24h' }
);
res.json({ token });
}
);
const bcrypt = require('bcryptjs');
// Register
app.post('/register', async (req, res) => {
const { email, password } = req.body;
// Hash password
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
const user = await User.create({
email,
password: hashedPassword
});
res.json({ user });
});
// Login
app.post('/login', async (req, res) => {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) {
return res.status(401).json({ error: 'Invalid credentials' });
}
// Compare password
const isValid = await bcrypt.compare(password, user.password);
if (!isValid) {
return res.status(401).json({ error: 'Invalid credentials' });
}
const token = jwt.sign(
{ userId: user.id, email: user.email },
secret,
{ expiresIn: '24h' }
);
res.json({ token });
});
// 1. Use HTTPS always
// 2. Store tokens securely
// 3. Short-lived access tokens
const token = jwt.sign(data, secret, { expiresIn: '15m' });
// 4. Use strong secrets
const secret = require('crypto')
.randomBytes(32)
.toString('hex');
// 5. Validate claims
jwt.verify(token, secret, (error, user) => {
if (error) throw error;
if (user.exp * 1000 < Date.now()) {
throw new Error('Token expired');
}
});
// 6. Handle token revocation
const tokenBlacklist = new Set();
app.post('/logout', (req, res) => {
const { token } = req.body;
tokenBlacklist.add(token);
res.json({ message: 'Logged out' });
});
function authenticateToken(req, res, next) {
const token = req.headers['authorization']?.split(' ')[1];
if (tokenBlacklist.has(token)) {
return res.status(401).json({ error: 'Token revoked' });
}
jwt.verify(token, secret, (error, user) => {
if (error) return res.status(403).json({ error: 'Invalid' });
req.user = user;
next();
});
}