Skip to main content

Authentication Best Practices

Implement secure authentication with JWT, OAuth, and modern security patterns for web applications.

14 min read
401 views82 likes18 comments
Authentication Best Practices

Authentication Best Practices

Implement secure authentication with JWT, OAuth, and multi-factor authentication in modern web applications.

Authentication Methods

Session-Based Authentication

Traditional approach using server-side sessions:

// Server creates a session after login
app.post('/login', async (req, res) => {
  const user = await verifyCredentials(req.body)
  req.session.userId = user.id
  res.json({ success: true })
})

JWT (JSON Web Tokens)

Stateless authentication with signed tokens:

import jwt from 'jsonwebtoken'

// Generate token
const token = jwt.sign(
  { userId: user.id, role: user.role },
  process.env.JWT_SECRET,
  { expiresIn: '7d' }
)

// Verify token middleware
function authenticate(req, res, next) {
  const token = req.headers.authorization?.split(' ')[1]
  if (!token) return res.status(401).json({ error: 'Unauthorized' })

  try {
    const payload = jwt.verify(token, process.env.JWT_SECRET)
    req.user = payload
    next()
  } catch {
    res.status(401).json({ error: 'Invalid token' })
  }
}

OAuth 2.0

Delegate authentication to trusted providers:

// NextAuth.js configuration
import NextAuth from 'next-auth'
import GoogleProvider from 'next-auth/providers/google'

export const { handlers, auth } = NextAuth({
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
})

Password Security

import bcrypt from 'bcryptjs'

// Hash password before storing
const hashedPassword = await bcrypt.hash(password, 12)

// Verify password during login
const isValid = await bcrypt.compare(inputPassword, storedHash)

Security Headers

import helmet from 'helmet'

app.use(helmet())
app.use(helmet.contentSecurityPolicy({
  directives: {
    defaultSrc: ["'self'"],
    scriptSrc: ["'self'", "'unsafe-inline'"],
  },
}))

Rate Limiting for Auth Endpoints

const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 5, // 5 attempts
  message: 'Too many login attempts, try again later',
})

app.post('/login', loginLimiter, loginHandler)

Conclusion

Good authentication keeps your users safe and your application secure. Always hash passwords, use HTTPS, implement rate limiting, and consider multi-factor authentication for sensitive applications.

Share this article

Subscribe to our newsletter

Get the latest articles, tutorials, and insights delivered straight to your inbox. No spam, unsubscribe anytime.

Related Articles

Modern CSS Techniques for 2024

Modern CSS Techniques for 2024

Explore the latest CSS features including container queries, cascade layers, and advanced grid layouts.

Read more
Getting Started with Next.js 15

Getting Started with Next.js 15

Learn about the latest features in Next.js 15 including async components, improved performance, and new routing capabilities.

Read more
Tailwind CSS: Beyond the Basics

Tailwind CSS: Beyond the Basics

Advanced Tailwind CSS techniques including custom plugins, dynamic classes, and performance optimization.

Read more

Comments (0)