OAuth 2.0 and JWT Authorization in TypeScript: Complete Guide
Modern web applications and APIs require reliable authentication and authorization mechanisms. The two most popular standards — OAuth 2.0 and JWT (JSON Web Tokens) — are often used together to create secure and scalable systems. In this article, we will explore how to implement OAuth 2.0 and JWT authorization in TypeScript using Express.js and popular libraries.
What are OAuth 2.0 and JWT?
OAuth 2.0 is an authorization protocol that allows applications to obtain limited access to user resources without sharing their credentials. It is widely used for social login (Google, GitHub, Facebook).
JWT (JSON Web Token) is a compact and self-contained token that contains user information and can be verified without querying a database. JWT is often used as the format for access tokens in OAuth 2.0.
Together, they form a powerful mechanism: OAuth 2.0 manages the token issuance process, while JWT ensures secure transmission and verification.
Project Setup and Dependency Installation
Let's create a new TypeScript project. Make sure you have Node.js installed (version 18+).
mkdir oauth-jwt-typescriptcd oauth-jwt-typescriptnpm init -yInstall the required dependencies:
npm install express jsonwebtoken passport passport-google-oauth20 dotenv bcryptjsnpm install -D typescript @types/express @types/jsonwebtoken @types/passport @types/passport-google-oauth20 @types/bcryptjs ts-node nodemonCreate the tsconfig.json file:
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "outDir": "./dist" }, "include": ["src/**/*"]}Project structure:
src/ ├── config/ │ └── passport.ts ├── controllers/ │ └── authController.ts ├── middleware/ │ └── authMiddleware.ts ├── models/ │ └── user.ts ├── routes/ │ └── authRoutes.ts ├── services/ │ └── jwtService.ts └── app.tsImplementing JWT Authorization
JWT tokens consist of three parts: header, payload, and signature. Let's look at a basic implementation in TypeScript.
Create a service for working with JWT (src/services/jwtService.ts):
import jwt from 'jsonwebtoken';import dotenv from 'dotenv';
dotenv.config();
const ACCESS_SECRET = process.env.JWT_ACCESS_SECRET || 'access-secret-key';const REFRESH_SECRET = process.env.JWT_REFRESH_SECRET || 'refresh-secret-key';
export interface TokenPayload { userId: string; email: string; role: string;}
export const generateAccessToken = (payload: TokenPayload): string => { return jwt.sign(payload, ACCESS_SECRET, { expiresIn: '15m' });};
export const generateRefreshToken = (payload: TokenPayload): string => { return jwt.sign(payload, REFRESH_SECRET, { expiresIn: '7d' });};
export const verifyAccessToken = (token: string): TokenPayload => { return jwt.verify(token, ACCESS_SECRET) as TokenPayload;};
export const verifyRefreshToken = (token: string): TokenPayload => { return jwt.verify(token, REFRESH_SECRET) as TokenPayload;};Create middleware for JWT verification (src/middleware/authMiddleware.ts):
import { Request, Response, NextFunction } from 'express';import { verifyAccessToken } from '../services/jwtService';
export interface AuthRequest extends Request { user?: { userId: string; email: string; role: string; };}
export const authenticateJWT = (req: AuthRequest, res: Response, next: NextFunction): void => { const authHea