Makrosites

Suas ideias em realidade digital!

Erro 401 e 403 em APIs PHP: diferenças, causas e como corrigir

Erro 401 e 403 em APIs PHP: diferenças, causas e como corrigir

Erro 401 e 403 em APIs PHP: por que isso confunde tanto?

Em APIs REST feitas em PHP, os erros 401 Unauthorized e 403 Forbidden são extremamente comuns — e também extremamente mal utilizados.

Apesar de parecidos, eles têm significados completamente diferentes. Usar o código errado prejudica:

---

Diferença direta: 401 vs 403

Status Significado Quando usar
401 Não autenticado Token ausente, inválido ou expirado
403 Autenticado, mas sem permissão Usuário existe, mas não pode acessar
---

Erro 401 Unauthorized (mais comum)

O erro 401 indica que a requisição não possui credenciais válidas.

Causas comuns

Exemplo de erro 401 em PHP

<?php
if (empty($_SERVER['HTTP_AUTHORIZATION'])) {
  http_response_code(401);
  echo json_encode(['error' => 'Token não informado']);
  exit;
}

Exemplo correto (Bearer Token)

<?php
$auth = $_SERVER['HTTP_AUTHORIZATION'] ?? '';

if (!preg_match('/Bearer\s+(.*)$/i', $auth, $matches)) {
  http_response_code(401);
  echo json_encode(['error' => 'Token inválido']);
  exit;
}

$token = trim($matches[1]);
// validar token no banco ou JWT
---

Erro 403 Forbidden (muito usado errado)

O erro 403 significa que o usuário está autenticado, mas não tem permissão para acessar aquele recurso.

Causas comuns

Exemplo correto de erro 403

<?php
if ($user['role'] !== 'admin') {
  http_response_code(403);
  echo json_encode(['error' => 'Acesso negado']);
  exit;
}
---

Fluxo correto de validação em APIs PHP

Siga sempre esta ordem:

  1. Validar token → 401
  2. Validar permissões → 403
  3. Executar ação
<?php
// 1) Autenticação
$user = Auth::validateToken(); // lança 401 se falhar

// 2) Autorização
if (!$user['can_edit']) {
  Response::error('Forbidden', 403);
}

// 3) Executa ação
---

401 e CORS: erro clássico

Se sua API usa CORS, o navegador envia uma requisição OPTIONS. Se você retornar 401 ou 403 no OPTIONS, o front quebra.

Solução

<?php
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
  http_response_code(200);
  exit;
}
---

Boas práticas recomendadas

---

Checklist rápido