Pular para o conteúdo

Fluxos de Autenticação

O Aura suporta 5 métodos de autenticação diferentes, cada um com seu fluxo e nível de confiança.

MétodoPrioridadeResultado
Azure AD SSOPrimárioJWT + cookie (12h, HttpOnly)
Login LocalSecundárioJWT + cookie (12h, HttpOnly)
Guest AccessConviteJWT guest + cookie (12h, allowedApps)
App VerificationComplementarRegistro no D1 (per-user per-app)
Internal API KeyAutomaçãoBypass JWT (rotas específicas)

Fluxo OAuth 2.0 + OIDC com Azure AD / Entra ID.

sequenceDiagram
    participant U as Usuário
    participant W as Worker (Hono)
    participant AZ as Azure AD
    participant GR as MS Graph
    participant DB as D1

    U->>W: GET /auth/microsoft
    W-->>U: 302 Redirect
    U->>AZ: Login (OAuth 2.0 authorize)
    Note over AZ: scope: openid profile<br/>email User.Read
    AZ-->>U: Callback com code + state
    U->>W: GET /auth/callback?code=X&state=Y
    W->>AZ: POST /token (troca code por access_token)
    AZ-->>W: access_token
    W->>GR: GET /v1.0/me (Bearer token)
    GR-->>W: { email, displayName }
    W->>W: Valida domínio vs ALLOWED_DOMAINS
    W->>DB: UPSERT auth_users
    W->>W: Assina JWT (HMAC-SHA256)
    W-->>U: Set-Cookie: profarma_session<br/>HttpOnly, Secure, SameSite=Lax, 12h

Domínios Permitidos (ALLOWED_DOMAINS):

  • profarma.dev
  • profarma.com.br
  • grupoprofarma.com.br
  • reded1000.com.br
  • State parameter: verificar CSRF protection
  • Redirect URI: verificar whitelist
  • Domínios: testar email de domínio não-autorizado
  • Code exchange: verificar se code é single-use

Autenticação email + password com bcrypt.

sequenceDiagram
    participant U as Usuário
    participant W as Worker
    participant DB as D1

    U->>W: POST /auth/login { email, password }
    W->>W: Rate limit check (5/15min por IP)
    alt Rate limit excedido
        W-->>U: 429 Too Many Requests
    else OK
        W->>DB: SELECT * FROM auth_users WHERE email = ?
        alt Usuário encontrado
            W->>W: bcrypt.verify(password, hash)
            alt Password válido
                W->>W: Assina JWT (HMAC-SHA256)
                W-->>U: Set-Cookie: profarma_session (12h)
            else Password inválido
                W-->>U: 401 Unauthorized (mensagem genérica)
            end
        else Não encontrado
            W-->>U: 401 Unauthorized (mensagem genérica)
        end
    end
EndpointLimiteJanela
/auth/login5 tentativas15 minutos
/auth/register3 registros1 hora
  • Brute force: testar rate limit enforcement
  • Timing attack: login com email inexistente vs password errado deve ter mesmo tempo
  • Password hash: bcrypt (resistente a timing attacks por design)

Acesso controlado por token de convite + Turnstile.

sequenceDiagram
    participant A as Admin
    participant W as Worker
    participant DB as D1
    participant G as Guest
    participant CF as Turnstile

    rect rgb(30, 40, 60)
    Note over A,DB: Etapa 1 — Criação do convite
    A->>W: POST /api/admin/guests<br/>{ email, allowed_apps }
    W->>DB: INSERT guest_invites<br/>(invite_token = UUID v4)
    W-->>A: Convite criado
    end

    rect rgb(30, 50, 40)
    Note over G,CF: Etapa 2 — Verificação do guest
    G->>W: GET /?invite=TOKEN
    W->>W: GET /auth/guest/verify?token=TOKEN
    W-->>G: HTML com Turnstile challenge
    G->>CF: Resolve Turnstile
    CF-->>G: turnstile_response
    G->>W: POST /auth/guest/verify<br/>{ token, turnstile_response }
    W->>CF: Valida Turnstile (server-side)
    CF-->>W: Válido
    W->>DB: Verifica invite_token
    W->>W: JWT (guest=true, allowedApps=[...])
    W-->>G: Set-Cookie: profarma_session
    end
  • Token guessing: UUIDs v4 são 122-bit random — impraticável
  • Token reuse: verificar se convite pode ser usado múltiplas vezes
  • Scope escalation: guest não deve acessar apps fora do allowedApps
  • Turnstile bypass: testar sem challenge response

Verificação per-app após login, usando Cloudflare Turnstile.

flowchart TD
    A[Usuário autenticado] -->|GET /optimizer| B{requireAppAuth}
    B -->|JWT válido| C{App verificado no D1?}
    C -->|Sim| D[Serve app]
    C -->|Não| E[Turnstile Challenge]
    E --> F[POST /auth/verify-access]
    F --> G{Turnstile válido?}
    G -->|Sim| H[Grava verificação no D1]
    H --> D
    G -->|Não| I[403 Forbidden]
    B -->|JWT inválido| J[Redirect → login]

    style D fill:#00aaaf,color:#fff
    style I fill:#ef4444,color:#fff
    style J fill:#ef4444,color:#fff
  • Replay: verificar se Turnstile response pode ser reutilizado
  • Skip: testar acesso direto a /optimizer/api/* sem verificação

Bypass de JWT para automação e AI agents.

flowchart TD
    A[Request com X-Internal-API-Key] --> B{Rota na allowlist?}
    B -->|Não| C[Rejeita → auth normal]
    B -->|Sim| D{Rota na denylist?}
    D -->|Bloqueada| E[403 Forbidden]
    D -->|Permitida| F{Rate limit OK?}
    F -->|Excedido| G[429 Too Many Requests]
    F -->|OK| H{Timing-safe compare}
    H -->|Inválida| I[401 Unauthorized]
    H -->|Válida| J[Acesso concedido]

    style J fill:#00aaaf,color:#fff
    style E fill:#ef4444,color:#fff
    style G fill:#f59e0b,color:#fff
    style I fill:#ef4444,color:#fff
RotaMotivo
/optimizer/api/catalog/publishOperação crítica — requer humano
/optimizer/api/catalog/approveOperação crítica — requer humano
/optimizer/api/settingsConfigurações — requer humano
/optimizer/api/adminAdmin — requer humano
  • Testar timing-safe comparison (constant-time)
  • Testar key via query param (deve ser rejeitada — apenas header)
  • Testar rotas bloqueadas com API key válida
  • Testar rate limit de 100/min