Security
Backend
JavaScript
Tutorial
Web Development
Ask anything about this article
Hi! I've read this article.
What would you like to know?
@farhan
Authentication is the foundation of every web application, yet it's one of the most misunderstood topics. Let's break down how OAuth 2.0 and JWT work, when to use each, and how to implement them properly.
OAuth 2.0 is an authorization framework that lets users grant third-party apps access to their data without sharing passwords.
1. User clicks "Login with Google"
2. App redirects to Google's auth page
3. User signs in and grants permission
4. Google redirects back with an authorization code
5. App exchanges the code for an access token (server-to-server)
6. App uses the access token to fetch user data from Google
| Grant Type | Use Case |
|---|---|
| Authorization Code | Web apps with a backend |
| Authorization Code + PKCE | SPAs and mobile apps |
| Client Credentials | Server-to-server (no user) |
| Refresh Token | Getting new access tokens |
JWT (JSON Web Token) is a compact, self-contained token format for securely transmitting information between parties.
header.payload.signature
eyJhbGciOiJIUzI1NiJ9. ← Header (algorithm)
eyJ1c2VySWQiOiIxMjMifQ. ← Payload (data)
SflKxwRJSMeKKF2QT4fwpMeJf36POk ← Signature (verification)
typescriptimport jwt from 'jsonwebtoken';
const token = jwt.sign(
{ userId: '123', role: 'admin' }, // Payload
process.env.JWT_SECRET, // Secret key
{ expiresIn: '15m' } // Options
);
typescripttry {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
console.log(decoded.userId); // "123"
} catch (error) {
console.log('Invalid or expired token');
}
OAuth 2.0 is the flow (how you get the token). JWT is the format (what the token looks like).
User → "Login with Google" → OAuth 2.0 Flow → Get user info
App → Create JWT with user info → Send to client
Client → Sends JWT in every request → Server verifies JWT
typescript// app/api/auth/[...nextauth]/route.ts
import NextAuth from 'next-auth';
import GoogleProvider from 'next-auth/providers/google';
const handler = NextAuth({
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
],
callbacks: {
async jwt({ token, user }) {
if (user) token.role = user.role;
return token;
},
async session({ session, token }) {
session.user.role = token.role;
return session;
}
}
});
export { handler as GET, handler as POST };
Authentication done right is invisible to the user. Authentication done wrong can compromise everything.