OAuth 2.0 e autorização JWT em TypeScript: guia prático

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: por que OAuth 2.0 e JWT são o padrão da autorização moderna

\n

No desenvolvimento web moderno, autenticação e autorização seguras são componentes criticamente importantes de qualquer aplicação. OAuth 2.0 e JWT (JSON Web Tokens) tornaram-se o padrão de facto para a construção de sistemas distribuídos. O OAuth 2.0 fornece um protocolo de acesso delegado, enquanto o JWT é um formato de token compacto e autossuficiente.

\n

Neste artigo, com exemplos práticos em TypeScript, vamos analisar como implementar o ciclo completo de autorização: desde a emissão de tokens até sua validação e renovação. Você aprenderá como proteger endpoints de API, implementar refresh tokens e tratar erros típicos.

\n\n

1. Configuração básica do projeto e instalação de dependências

\n

Para começar, vamos criar um projeto em Node.js com TypeScript. Certifique-se de ter Node.js (versão 18+) e npm instalados.

\n
mkdir oauth-jwt-typescript\ncd oauth-jwt-typescript\nnpm init -y\nnpm install express cors dotenv jsonwebtoken bcrypt\nnpm install -D typescript @types/express @types/cors @types/jsonwebtoken @types/bcrypt ts-node nodemon\nnpx tsc --init
\n

Vamos configurar o tsconfig.json para trabalhar com módulos ES e tipos estritos. No arquivo .env, adicionaremos as chaves secretas:

\n
ACCESS_TOKEN_SECRET=your-super-secret-access-key\nREFRESH_TOKEN_SECRET=your-super-secret-refresh-key\nACCESS_TOKEN_EXPIRES_IN=15m\nREFRESH_TOKEN_EXPIRES_IN=7d
\n\n

2. Implementação da geração e verificação de tokens JWT

\n

Vamos criar a utilitária src/utils/jwt.ts para trabalhar com tokens. Usaremos dois tipos de tokens: Access Token (de curta duração) e Refresh Token (de longa duração).

\n
import jwt from 'jsonwebtoken';\nimport dotenv from 'dotenv';\n\ndotenv.config();\n\ninterface TokenPayload {\n  userId: string;\n  email: string;\n  role: 'user' | 'admin';\n}\n\nexport const generateAccessToken = (payload: TokenPayload): string => {\n  return jwt.sign(payload, process.env.ACCESS_TOKEN_SECRET!, {\n    expiresIn: process.env.ACCESS_TOKEN_EXPIRES_IN || '15m',\n  });\n};\n\nexport const generateRefreshToken = (payload: TokenPayload): string => {\n  return jwt.sign(payload, process.env.REFRESH_TOKEN_SECRET!, {\n    expiresIn: process.env.REFRESH_TOKEN_EXPIRES_IN || '7d',\n  });\n};\n\nexport const verifyAccessToken = (token: string): TokenPayload => {\n  return jwt.verify(token, process.env.ACCESS_TOKEN_SECRET!) as TokenPayload;\n};\n\nexport const verifyRefreshToken = (token: string): TokenPayload => {\n  return jwt.verify(token, process.env.REFRESH_TOKEN_SECRET!) as TokenPayload;\n};
\n

Observe: usamos tipagem estrita para o payload. Isso garante que o token sempre terá os campos necessários.

\n\n

3. Criação de middleware para proteção de rotas

\n

Agora vamos implementar o middleware que verificará a presença e validade do Access Token no cabeçalho Authorization. Crie src/middleware/auth.ts:

\n
import { Request, Response, NextFunction } from 'express';\nimport { verifyAccessToken } from '../utils/jwt';\n\nexport interface AuthRequest extends Request {\n  user?: {\n    userId: string;\n    email: string;\n    role: 'user' | 'admin';\n  };\n}\n\nexport const authenticate = (req: AuthRequest, res: Response, next: NextFunction): void => {\n  const authHeader = req.headers['authorization'];\n  const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN\n\n  if (!token) {\n    res.status(401).json({ error: 'Access token is required' });\n    return;\n  }\n\n  try {\n    const decoded = verifyAccessToken(token);\n    req.user = decoded;\n    next();\n  } catch (error) {\n    res.status(403).json({ error: 'Invalid or expired access token' });\n  }\n};\n\nexport const authorizeRole = (...roles: string[]) => {\n  return (req: AuthRequest, res: Response, next: NextFunction): void => {\n    if (!req.user || !roles                

Blogs

Book Recommendations