Módulo Auth
Como usar autenticação em qualquer módulo — de forma simples, com uma linha de código.
O módulo Auth é desacoplado — funciona com qualquer entidade que implemente AuthenticatableInterface. A fachada Auth encapsula toda a complexidade em métodos curtos e claros.
O que o módulo Auth oferece
| O que você precisa | Como fazer |
|---|---|
| Proteger uma rota (qualquer usuário logado) | Auth::user() |
| Proteger uma rota (só admin) | Auth::admin() |
| Obter o usuário logado no Controller | Auth::current($request) |
| Obter o ID do usuário logado | Auth::id($request) |
| Verificar se está logado (lança 401) | Auth::check($request) |
| Verificar se é admin (lança 403) | Auth::checkAdmin($request) |
| Autenticação opcional (conteúdo diferente) | Auth::optional() |
| Rate limit sem autenticação | Auth::limit(10) |
Protegendo rotas
Importe Auth no Routes/web.php do seu módulo e use como terceiro argumento:
<?php
use Src\Kernel\Auth;
use Src\Modules\Produto\Controllers\ProdutoController;
/** @var \Src\Kernel\Contracts\RouterInterface $router */
// Pública — sem autenticação
$router->get('/api/produtos', [ProdutoController::class, 'listar']);
$router->get('/api/produtos/{id}', [ProdutoController::class, 'buscar']);
// Privada — qualquer usuário logado
$router->get('/api/meus-produtos', [ProdutoController::class, 'meus'], Auth::user());
// Admin — só admin_system
$router->post('/api/admin/produtos', [ProdutoController::class, 'criar'], Auth::admin());
$router->put('/api/admin/produtos/{id}', [ProdutoController::class, 'atualizar'], Auth::admin());
$router->delete('/api/admin/produtos/{id}', [ProdutoController::class, 'deletar'], Auth::admin());
// Com rate limit — 10 req/min por IP
$router->post('/api/produtos/buscar', [ProdutoController::class, 'buscarAvancado'], Auth::user(limit: 10));
// Admin com rate limit + proteção de banco
$router->post('/api/admin/importar', [ProdutoController::class, 'importar'], Auth::admin(limit: 5, db: true));
Acessando o usuário no Controller
Use a fachada Auth para obter o usuário autenticado dentro do Controller:
<?php
namespace Src\Modules\Produto\Controllers;
use Src\Kernel\Auth;
use Src\Kernel\Http\Request\Request;
use Src\Kernel\Http\Response\Response;
use Src\Modules\Produto\Services\ProdutoService;
class ProdutoController
{
public function __construct(private ProdutoService $service) {}
// Rota pública — usuário pode ou não estar logado
public function listar(Request $request): Response
{
$userId = Auth::id($request); // null se não logado
$produtos = $this->service->listar($userId);
return Response::json(['produtos' => $produtos]);
}
// Rota privada — Auth::user() já garante que está logado
public function meus(Request $request): Response
{
$user = Auth::current($request); // nunca null aqui
$produtos = $this->service->listarPorUsuario($user->getAuthId());
return Response::json(['produtos' => $produtos]);
}
// Rota admin — Auth::admin() já garante que é admin_system
public function criar(Request $request): Response
{
$user = Auth::current($request);
$produto = $this->service->criar($request->body ?? [], $user->getAuthId());
return Response::json(['produto' => $produto], 201);
}
// Verificação manual dentro do Controller (sem middleware na rota)
public function deletar(Request $request, string $id): Response
{
try {
Auth::checkAdmin($request); // lança 403 se não for admin_system
$this->service->deletar($id);
return Response::json(['message' => 'Removido.']);
} catch (\DomainException $e) {
return Response::json(['error' => $e->getMessage()], $e->getCode() ?: 403);
}
}
}
Usando Auth com sua própria entidade
O módulo Auth funciona com qualquer entidade — não só com Usuario. Para usar com uma entidade própria (ex: Cliente, Funcionario), siga 3 passos:
Implemente AuthenticatableInterface na entidade
<?php
namespace Src\Modules\Cliente\Entities;
use Src\Kernel\Contracts\AuthenticatableInterface;
class Cliente implements AuthenticatableInterface
{
public function __construct(
private string $id,
private string $email,
private string $senhaHash,
private bool $ativo
) {}
// Métodos obrigatórios da interface
public function getAuthId(): string { return $this->id; }
public function getAuthEmail(): string { return $this->email; }
public function getAuthUsername(): ?string { return null; } // sem username
public function getAuthRole(): string { return 'cliente'; }
public function isAtivo(): bool { return $this->ativo; }
public function isEmailVerificado(): bool { return true; }
public function verificarSenha(string $senha): bool
{
return password_verify($senha, $this->senhaHash);
}
}
Implemente UserRepositoryInterface no Repository
<?php
namespace Src\Modules\Cliente\Repositories;
use PDO;
use Src\Kernel\Contracts\UserRepositoryInterface;
use Src\Modules\Cliente\Entities\Cliente;
class ClienteRepository implements UserRepositoryInterface
{
public function __construct(private PDO $pdo) {}
public function buscarPorEmail(string $email): ?object
{
$stmt = $this->pdo->prepare('SELECT * FROM clientes WHERE email = :e LIMIT 1');
$stmt->execute([':e' => $email]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
return $row ? new Cliente($row['id'], $row['email'], $row['senha_hash'], (bool)$row['ativo']) : null;
}
public function buscarPorUsername(string $username): ?object { return null; }
public function buscarPorUuid(string $uuid): ?object
{
$stmt = $this->pdo->prepare('SELECT * FROM clientes WHERE id = :id LIMIT 1');
$stmt->execute([':id' => $uuid]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
return $row ? new Cliente($row['id'], $row['email'], $row['senha_hash'], (bool)$row['ativo']) : null;
}
// Stubs obrigatórios pela interface — implemente se precisar
public function marcarEmailComoVerificado(string $uuid, bool $v = true): void {}
public function salvarTokenRecuperacaoSenha(string $uuid, string $token): void {}
public function buscarPorTokenRecuperacaoSenha(string $token): ?object { return null; }
public function limparTokenRecuperacaoSenha(string $uuid): void {}
public function salvarTokenVerificacaoEmail(string $uuid, string $token): void {}
public function buscarPorTokenVerificacaoEmail(string $token): ?object { return null; }
}
Registre no container em index.php
Este é o único lugar fora do módulo que precisa ser alterado — e só uma vez:
// index.php — substitua o binding de UserRepositoryInterface
$container->bind(
\Src\Kernel\Contracts\UserRepositoryInterface::class,
static fn() => new \Src\Modules\Cliente\Repositories\ClienteRepository(
\Src\Kernel\Database\ModuleConnectionResolver::forModule('Cliente')
),
true
);
A partir daí, Auth::user(), Auth::admin(), Auth::current() e todos os outros métodos funcionam automaticamente com a entidade Cliente.
Referência completa da fachada Auth
| Método | Uso | Descrição |
|---|---|---|
Auth::user() | Middleware de rota | Exige qualquer usuário logado |
Auth::user(limit: 10) | Middleware de rota | Usuário logado + rate limit 10/min |
Auth::user(db: true) | Middleware de rota | Usuário logado + circuit breaker |
Auth::admin() | Middleware de rota | Exige admin_system |
Auth::api() | Middleware de rota | Token de API (machine-to-machine) |
Auth::optional() | Middleware de rota | Autenticação opcional |
Auth::limit(5) | Middleware de rota | Só rate limit, sem auth |
Auth::db() | Middleware de rota | Só circuit breaker |
Auth::current($req) | Controller | Usuário logado ou null |
Auth::id($req) | Controller | UUID do usuário ou null |
Auth::role($req) | Controller | Nível de acesso ou null |
Auth::check($req) | Controller | Retorna usuário ou lança 401 |
Auth::checkAdmin($req) | Controller | Retorna usuário ou lança 403 |
Auth::checkRole($req, 'admin') | Controller | Verifica papel ou lança 403 |
Auth::current() retorna
Retorna um objeto que implementa AuthenticatableInterface com os métodos:
getAuthId() — ID único (UUID)
getAuthEmail() — e-mail
getAuthUsername() — username (pode ser null)
getAuthRole() — nível de acesso (ex: 'usuario', 'admin_system')
isAtivo() — se a conta está ativa
isEmailVerificado() — se o e-mail foi verificado