agoravaisedeusquiser

This commit is contained in:
2026-05-28 14:56:25 -05:00
parent de6fa39956
commit c924753210
3 changed files with 31 additions and 32 deletions

View File

@@ -1,10 +1,12 @@
from fastapi import Depends, HTTPException, status from fastapi import Request
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import jwt import jwt
from pydantic import BaseModel from pydantic import BaseModel
from app.core.config import settings from app.core.config import settings
import textwrap
security = HTTPBearer() class AuthException(Exception):
def __init__(self, message: str):
self.message = message
class UserAuth(BaseModel): class UserAuth(BaseModel):
id: str id: str
@@ -16,17 +18,25 @@ def format_public_key(key: str) -> str:
footer = "-----END PUBLIC KEY-----" footer = "-----END PUBLIC KEY-----"
if header in key and footer in key: if header in key and footer in key:
# Extrai o miolo, remove todos os espaços e quebras de linha
body = key.replace(header, "").replace(footer, "") body = key.replace(header, "").replace(footer, "")
body = "".join(body.split()) body = "".join(body.split())
body = "\n".join(textwrap.wrap(body, width=64))
return f"{header}\n{body}\n{footer}" return f"{header}\n{body}\n{footer}"
return key return key
def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)) -> UserAuth: def get_current_user(request: Request) -> UserAuth:
token = credentials.credentials auth_header = request.headers.get("authorization")
if not auth_header:
raise AuthException("Missing Authorization header")
parts = auth_header.split(" ")
if len(parts) != 2 or parts[0].lower() != "bearer":
raise AuthException("Authorization must be Bearer token")
token = parts[1]
try: try:
# Garante que a chave terá o formato PEM válido, independentemente de como foi definida no .env
public_key = format_public_key(settings.JWT_PUBLIC_KEY_PEM) public_key = format_public_key(settings.JWT_PUBLIC_KEY_PEM)
payload = jwt.decode( payload = jwt.decode(
@@ -39,30 +49,10 @@ def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(securit
sub = payload.get("sub") sub = payload.get("sub")
if not sub or not str(sub).strip(): if not sub or not str(sub).strip():
raise HTTPException( raise AuthException("Invalid token claims")
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid token claims",
headers={"WWW-Authenticate": "Bearer"},
)
return UserAuth(id=str(sub), token=token) return UserAuth(id=str(sub), token=token)
except jwt.ExpiredSignatureError:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Token expired",
headers={"WWW-Authenticate": "Bearer"},
)
except jwt.InvalidTokenError:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid access token",
headers={"WWW-Authenticate": "Bearer"},
)
except Exception as e: except Exception as e:
import traceback import traceback
traceback.print_exc() # Imprime no log do docker para ajudar a debugar traceback.print_exc()
raise HTTPException( raise AuthException("Invalid or expired access token")
status_code=status.HTTP_401_UNAUTHORIZED,
detail=f"Could not validate credentials: {str(e)}",
headers={"WWW-Authenticate": "Bearer"},
)

View File

@@ -1,6 +1,7 @@
from fastapi import FastAPI, Depends from fastapi import FastAPI, Depends, Request
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from app.core.security import get_current_user, UserAuth from fastapi.responses import JSONResponse
from app.core.security import get_current_user, UserAuth, AuthException
from app.core.config import settings from app.core.config import settings
from app.api.v1.api import api_router from app.api.v1.api import api_router
from app.db.database import Base, engine from app.db.database import Base, engine
@@ -23,6 +24,13 @@ app.add_middleware(
app.include_router(api_router, prefix=settings.API_V1_STR) app.include_router(api_router, prefix=settings.API_V1_STR)
@app.exception_handler(AuthException)
async def auth_exception_handler(request: Request, exc: AuthException):
return JSONResponse(
status_code=401,
content={"message": exc.message}
)
@app.get("/") @app.get("/")
def root(current_user: UserAuth = Depends(get_current_user)): def root(current_user: UserAuth = Depends(get_current_user)):
return {"message": "Bem-vindo ao Microsserviço de Catálogo do GameVerse"} return {"message": "Bem-vindo ao Microsserviço de Catálogo do GameVerse"}

1
jwtpdf.md Normal file
View File

@@ -0,0 +1 @@
2. O que validar Para toda rota protegida: Authorization ler extrair Bearer <token> validar assinatura RS256 com JWT_PUBLIC_KEY_PEM 1 Guia: validar JWT nos serviços consumidoresvalidar iss , aud e exp validar se sub existe request.auth = { id: sub, token } montar Se algo falhar, retornar 401 . 3) Exemplo prático (Node/Express + jose) import express from 'express' import { importSPKI, jwtVerify } from 'jose' const app = express() const ISSUER = process.env.JWT_ISSUER! const AUDIENCE = process.env.JWT_AUDIENCE! const PUBLIC_KEY_PEM = process.env.JWT_PUBLIC_KEY_PEM!.repl ace(/\\n/g, '\n') let publicKeyPromise: ReturnType<typeof importSPKI> | null = null function getPublicKey() { if (!publicKeyPromise) { publicKeyPromise = importSPKI(PUBLIC_KEY_PEM, 'RS256') } return publicKeyPromise } function authMiddleware() { return async (req, res, next) => { try { const authHeader = req.header('authorization') if (!authHeader) { return res.status(401).json({ message: 'Missing Aut horization header' }) } 2 Guia: validar JWT nos serviços consumidoresconst [scheme, token] = authHeader.split(' ') if (!scheme || !token || scheme.toLowerCase() !== 'be arer') { return res.status(401).json({ message: 'Authorizati on must be Bearer token' }) } const publicKey = await getPublicKey() const { payload } = await jwtVerify(token, publicKey, { issuer: ISSUER, audience: AUDIENCE, algorithms: ['RS256'] }) if (typeof payload.sub !== 'string' || !payload.sub.t rim()) { return res.status(401).json({ message: 'Invalid tok en claims' }) } req.auth = { id: payload.sub, token } return next() } catch { return res.status(401).json({ message: 'Invalid or ex pired access token' }) } } } // middleware em todas requisições que lidam com dados do u 3 Guia: validar JWT nos serviços consumidoressuário app.get('/profile/me', authMiddleware(), (req, res) => { return res.json({ userId: req.auth.id }) }) 4) Propagação entre serviços (A -> B) Se for necessário, serviços podem se comunicar entre si. Quando a API A chamar a API B em nome do usuário: repasse o mesmo Authorization: Bearer <token> a API B valida esse token com JWT_PUBLIC_KEY_PEM (mesmo conteúdo do ) a API B usa sub como identidade confiável .env o serviço que recebe a requisição extrai o token e válida ele (conforme procedimento acima): // extração do token por meio do header const authHeader = req.header('authorization') 5) Checklist rápido middleware valida assinatura + iss + aud + exp sub obrigatório, é ele que referencia o ID do usuário autenticado retorna 401 para token ausente/inválido/expirado usa sub como ID confiável