PHP MVCDOCUMENTAÇÃO
v2.0.0

Autenticação

Autenticação web via sessão/cookie e autenticação API por token Bearer.

Web

Framework\Auth\Auth usa o model App\Models\User por padrão. attempt(email,password,remember=false) autentica credenciais e pode criar cookie remember; check(), guest(), user(), id(), role(), is(), isAny(), require() e requireRole() consultam/guardam acesso. logout() encerra o estado de autenticação. Role não equivale a uma ACL completa.

Fluxo de exemplo

As rotas Web de login, registro e recuperação estão em routes/web.php; requests específicos em app/Http/Requests/Auth/; controller/service/model na camada app/. Senhas são verificadas com password_verify() e salvas com bcrypt cost 12 no exemplo de User.

API Bearer

A API emite token aleatório; persiste apenas SHA-256, devolve texto puro somente no login e o cliente deve guardá-lo. Cada request protegida envia Authorization: Bearer <token>. Token pode ter data de expiração; logout revoga o token usado. Middleware atualiza last_used_at.

Authorization: Bearer seu_token

Essa autenticação usa ApiAuthContext, separada da sessão web; consulte API HTTP e endpoints próprios.

Recuperação de senha

Tokens de redefinição armazenam hash, expiram em uma hora e são consumidos após uso. A requisição de recuperação não valida existência de e-mail para evitar enumeração; o controller verifica de modo silencioso.

O código de exemplo define perfis como strings (member/admin/editor em requests), não oferece um sistema completo de permissões por recurso. Proteja operações novas com middleware/autorização explícitos.

Web · credenciais viram sessão

No fluxo real, POST /auth/login passa GuestMiddleware, CsrfMiddleware e RateLimitMiddleware:login. LoginRequest valida e normaliza entrada; AuthService delega a Auth::attempt(), que chama User::authenticate(), cria sessão segura e pode gravar remember-me. A action então redireciona para dashboard ou volta com flash sem reenviar senha.

// No fluxo Web, a aplicação já faz esta chamada dentro de AuthService::login().
if (\Framework\Auth\Auth::attempt($email, $password, $remember)) {
    // usuário autenticado na sessão; continue com redirect Web
}
MétodoUsoResultado
Auth::attempt($email,$password,$remember=false)Autenticar por Model configuradobool; em sucesso chama loginUser().
check(), guest()Verificar estado webbool; conta ativa é revalidada.
user(), id(), role()Ler identidade da sessãoobject|null, int|null e string.
is($role), isAny(...$roles)Checar rolebool; não substitui autorização por recurso.
logout()Encerrar sessão e invalidar remember tokenvoid.

API · token Bearer não é cookie de sessão

POST /api/v1/auth/login retorna o token em texto claro apenas na resposta de emissão. A aplicação armazena o hash; chamadas seguintes enviam Authorization: Bearer. ApiAuthMiddleware valida o token e alimenta ApiAuthContext. Logout revoga o token atual; /auth/me devolve o usuário transformado por UserResource.

curl -X POST http://localhost:8000/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"email":"ana@example.com","password":"SUA_SENHA"}'

# Use o token devolvido sem colocá-lo em URL/log.
curl http://localhost:8000/api/v1/auth/me \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Accept: application/json"
A autenticação Web depende da sessão/cookie e CSRF em operações mutáveis; a API usa token Bearer e não depende da sessão Web. No código atual, conta inativa também resulta em 401 no login, porque User::authenticate() já a rejeita antes da checagem 403 subsequente do controller. Não reutilize um mecanismo como se o outro o substituísse.

As contas admin@example.com e user@example.com do UserSeeder usam senhas demo previsíveis. São dados locais de demonstração, não credenciais seguras; altere-as antes de qualquer ambiente acessível. Veja Sessões/CSRF e endpoints API.

Modelos reais de token da aplicação

App\Models\ApiToken::issue() gera um segredo aleatório e persiste somente SHA-256; o texto puro é retornado somente na emissão. findValidByPlainToken() verifica hash/expiração; touchLastUsed() registra uso e revoke()/revokeAllForUser() revogam tokens. O Repository encapsula essas operações. Não grave o token puro em logs ou URLs.

App\Models\RedefinicaoSenha possui createToken(), findValid() e consume(): o token é armazenado como hash, expira em uma hora e é de uso único. O controller de demonstração responde sem confirmar se um e-mail existe para reduzir enumeração.

StoreUserRequest é um exemplo sem rota UserController de criação no projeto e sua regra unique contém {id}. Como a rota atual de criação não existe para fornecer esse parâmetro, instanciá-la sem routeParams dispara RuntimeException por placeholder não resolvido. Remova/adapte o placeholder conforme a rota real antes de usar.

Guards, getters e fluxo de controle

Auth::require(string $redirectTo = 'auth/login'): void exige sessão autenticada; na falha redireciona e encerra. Auth::requireRole(string $role, string $redirectTo = 'dashboard'): void compara a role atual, redireciona/encerra na falha e, no caminho de navegador, mantém status 403. Exemplo:

\Framework\Auth\Auth::require('/auth/login');
\Framework\Auth\Auth::requireRole('admin', '/dashboard');

requireRole() é uma comparação simples de role, não ACL, matriz de permissões nem autorização por recurso. Aplique middleware/guard antes da action. Métodos como Auth::user(), id() e role() são getters da identidade da sessão, não revalidam a conta no banco; use Auth::check(), middleware de autenticação ou Auth::is()/isAny() como guard conforme o caso.

Destino padrão e caminho relativo: os defaults de Auth::require() (auth/login) e Auth::requireRole() (dashboard) não começam com /. Os middlewares também chamam redirect() com destinos relativos. Como o helper atual os rejeita, o destino pode cair em APP_URL// em vez da rota pretendida. Quando chamar o guard diretamente, passe caminho com barra inicial (por exemplo, /auth/login); a correção dos defaults exige mudança de código fora do escopo.

Tokens Bearer: emissão, expiração e revogação

ApiTokenRepository::issue(int $userId, string $name = 'api', ?string $expiresAt = null): array emite token e retorna o token puro uma única vez; o banco persiste apenas seu hash SHA-256. O login API atual chama a emissão sem data de expiração, portanto expires_at fica NULL e o token não expira por tempo automaticamente. Defina uma política operacional de TTL e revogação para produção e passe uma data explícita quando apropriado.

As demais assinaturas são findValidByPlainToken(string $plain): object|false, touchLastUsed(int $id): void, revoke(int $id): bool e revokeAllForUser(int $userId): bool. A busca rejeita token expirado; o texto puro só existe no retorno da emissão, então não é recuperável posteriormente. revokeAllForUser() é operação de Model/Repository, não endpoint HTTP que o framework exponha automaticamente.

Remember-me

Auth::recoverFromCookie(): bool deve ser chamado no bootstrap no ponto previsto pela aplicação. A recuperação só aceita conta ativa; cookie inválido/expirado é limpo, e o token persistente é rotacionado após recuperação. O retorno booleano indica se uma identidade foi recuperada. Não trate um cookie persistente como autorização suficiente sem validar essa condição.

Redefinição de senha: ordem e atomicidade

O fluxo implementado é findValid() → updatePassword() → consume(); o token expira em uma hora e a criação invalida token anterior. A consulta/alteração/consumo não forma por si só uma operação atômica: duas requisições concorrentes podem validar o mesmo token antes de marcá-lo consumido. Não prometa garantia forte de uso único sob concorrência sem transação/consumo atômico no framework. Evite expor token em logs ou mensagens públicas.