OAuth 2.0 e autorização JWT em TypeScript: guia completo
Aplicações web modernas e APIs exigem mecanismos robustos de autenticação e autorização. Os dois padrões mais populares — OAuth 2.0 e JWT (JSON Web Tokens) — são frequentemente usados juntos para criar sistemas seguros e escaláveis. Neste artigo, vamos analisar como implementar autorização OAuth 2.0 e JWT em TypeScript, usando Express.js e bibliotecas populares.
O que são OAuth 2.0 e JWT?
OAuth 2.0 é um protocolo de autorização que permite que aplicativos obtenham acesso limitado aos recursos de um usuário sem transmitir suas credenciais. Ele é amplamente usado para login através de redes sociais (Google, GitHub, Facebook).
JWT (JSON Web Token) é um token compacto e autossuficiente que contém informações sobre o usuário e pode ser verificado sem consultar um banco de dados. JWT é frequentemente usado como formato de access-tokens no OAuth 2.0.
Juntos, eles formam um mecanismo poderoso: OAuth 2.0 gerencia o processo de emissão de tokens, enquanto o JWT garante sua transmissão segura e verificação.
Configuração do projeto e instalação de dependências
Vamos criar um novo projeto em TypeScript. Certifique-se de ter o Node.js instalado (versão 18+).
mkdir oauth-jwt-typescriptcd oauth-jwt-typescriptnpm init -yInstale as dependências necessárias:
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 nodemonCrie o arquivo tsconfig.json:
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "outDir": "./dist" }, "include": ["src/**/*"]}Estrutura do projeto:
src/ ├── config/ │ └── passport.ts ├── controllers/ │ └── authController.ts ├── middleware/ │ └── authMiddleware.ts ├── models/ │ └── user.ts ├── routes/ │ └── authRoutes.ts ├── services/ │ └── jwtService.ts └── app.tsImplementação da autorização JWT
Os tokens JWT consistem em três partes: cabeçalho (header), payload (payload) e assinatura (signature). Vamos considerar uma implementação básica em TypeScript.
Crie um serviço para trabalhar com 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;};Crie um middleware para verificar JWT (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