Integracao Autenticacao

🔐 Guia de Integração de Autenticação - C-Suite

Visão Geral

Este guia explica como integrar o sistema de autenticação centralizado (csuite-auth) em todos os serviços do ecossistema C-Suite.

Arquitetura

Cliente
  │
  ├─> POST /auth/login (csuite-auth)
  │   └─> Retorna: { access_token, refresh_token, user }
  │
  └─> GET /api/protected (qualquer serviço)
      └─> Header: Authorization: Bearer <token>
      └─> Serviço valida token via csuite-auth ou common_auth

Módulos Disponíveis

1. common/common_sso.py

2. common/common_auth.py

Integração Passo a Passo

Passo 1: Adicionar Imports

# No main.py do serviço
AUTH_ENABLED = os.getenv("AUTH_ENABLED", "false").lower() == "true"
if AUTH_ENABLED:
    try:
        from common.common_sso import get_current_user_from_token, get_current_user_optional
        from common.common_auth import require_role
    except ImportError:
        AUTH_ENABLED = False
        logger.warning("Autenticação não disponível")

Passo 2: Proteger Endpoints

Opção A: Autenticação Obrigatória

from fastapi import Depends

@app.get("/api/protected")
async def protected_endpoint(
    current_user: dict = Depends(get_current_user_from_token)
):
    org_id = current_user.get("org_id")
    user_id = current_user.get("user_id")
    # Usa org_id e user_id do token
    return {"data": "protegido", "org_id": org_id}

Opção B: Autenticação Opcional

@app.get("/api/public-or-protected")
async def optional_auth_endpoint(
    current_user: Optional[dict] = Depends(get_current_user_optional)
):
    if current_user:
        # Usuário autenticado
        return {"data": "personalizado", "user": current_user["email"]}
    else:
        # Usuário não autenticado - retorna dados públicos
        return {"data": "público"}

Opção C: Verificar Roles

@app.post("/api/admin-only")
async def admin_endpoint(
    current_user: dict = Depends(get_current_user_from_token),
    _: None = Depends(require_role("admin", "super_admin"))
):
    return {"message": "Apenas admins podem acessar"}

Passo 3: Habilitar Autenticação

Adicione variável de ambiente no docker-stack.yml:

environment:
  - AUTH_ENABLED=true
  - AUTH_SERVICE_URL=https://csuite.internut.com.br/auth

Exemplo Completo: Cashflow

# app/routers/cash_accounts.py
from fastapi import APIRouter, Depends, HTTPException
from common.common_sso import get_current_user_from_token
from common.common_errors import CSuiteError, ErrorCode

router = APIRouter()

@router.post("/cash-accounts", response_model=CashAccountResponse)
async def create_cash_account(
    account: CashAccountCreate,
    current_user: dict = Depends(get_current_user_from_token),  # ← Adicionado
    db: AsyncSession = Depends(get_db)
):
    """Cria uma nova conta de caixa"""
    # Usa org_id do token para isolar dados
    org_id = current_user.get("org_id")
    if org_id:
        account.org_id = org_id  # Garante que a conta pertence à org do usuário

    return await CashAccountService.create_account(db, account)

@router.get("/cash-accounts", response_model=List[CashAccountResponse])
async def list_cash_accounts(
    active_only: bool = True,
    current_user: dict = Depends(get_current_user_from_token),  # ← Adicionado
    db: AsyncSession = Depends(get_db)
):
    """Lista todas as contas de caixa da organização do usuário"""
    org_id = current_user.get("org_id")
    if not org_id:
        raise CSuiteError(
            code=ErrorCode.UNAUTHORIZED,
            message="Organização não identificada",
            status_code=401
        )

    # Filtra por org_id
    return await CashAccountService.list_accounts(db, active_only, org_id=org_id)

SSO (Single Sign-On)

O SSO funciona automaticamente quando:
1. Usuário faz login em /auth/login
2. Token JWT é armazenado em cookie csuite_access_token
3. Todos os serviços validam o mesmo token

O csuite-auth pode configurar cookies automaticamente. Para habilitar:

# No csuite-auth/app/routers/auth.py
@router.post("/login")
async def login(request: LoginRequest, response: Response):
    # ... autenticação ...

    # Define cookie para SSO
    response.set_cookie(
        key="csuite_access_token",
        value=tokens["access_token"],
        max_age=30 * 60,  # 30 minutos
        httponly=True,
        secure=True,
        samesite="lax",
        path="/"
    )

    return tokens

Rate Limiting

Já integrado automaticamente via common/common_rate_limit.py:

# No main.py
from common.common_rate_limit import RateLimitMiddleware
app.add_middleware(RateLimitMiddleware, enabled=True)

Configuração via env:
- RATE_LIMIT_ENABLED=true
- RATE_LIMIT_REQUESTS_PER_MINUTE=60
- RATE_LIMIT_REQUESTS_PER_HOUR=1000

Tratamento de Erros Padronizado

Todos os serviços já usam common/common_errors.py:

from common.common_errors import CSuiteError, ErrorCode

# Em um endpoint
if not resource:
    raise CSuiteError(
        code=ErrorCode.NOT_FOUND,
        message="Recurso não encontrado",
        status_code=404,
        details={"resource_id": resource_id}
    )

Checklist de Integração

Migração Gradual

Para serviços em produção, recomenda-se migração gradual:

  1. Fase 1: Adicionar autenticação opcional (get_current_user_optional)
  2. Fase 2: Habilitar autenticação obrigatória em endpoints críticos
  3. Fase 3: Habilitar autenticação em todos os endpoints

Isso permite testar sem quebrar clientes existentes.

🔊 Text-to-Speech

1.0x
1.0
Pronto para reproduzir