Skip to content

Autenticación ​

Arrel autentica con Sanctum en modo SPA: cookies de sesión protegidas con CSRF, sin tokens que gestionar. Sobre esta base hay tres capas opcionales: la verificación del correo, un segundo factor y las notificaciones de la campana.

Configurar Sanctum ​

La aplicación debe añadir el dominio del panel a sanctum.stateful (y, en desarrollo, el origen del servidor de Vite si trabajas en modo dev):

php
config([
    'sanctum.stateful' => array_merge(
        config('sanctum.stateful', []),
        ['tu-dominio.test', 'localhost:5173'],
    ),
]);

La API de autenticación vive bajo /arrel/api/, sea cual sea el prefijo del panel:

RutaQué hace
POST /arrel/api/loginInicia la sesión con email y password.
POST /arrel/api/login/two-factorResuelve el segundo factor de un inicio de sesión pendiente.
POST /arrel/api/logoutCierra la sesión.
GET /arrel/api/userEl usuario autenticado.

El resto de la API queda detrás de auth:sanctum, la verificación del correo y el segundo factor.

Límites de intentos ​

  • El inicio de sesión admite cinco intentos fallidos por combinación de correo y dirección IP. Pasado el límite, la respuesta es un error de validación con el mensaje arrel::auth.throttle.
  • Un inicio de sesión que espera el segundo factor caduca a los cinco minutos, o tras cinco códigos incorrectos. El usuario debe volver a escribir correo y contraseña.
  • Los endpoints de login tienen además un límite de 10 peticiones por minuto a nivel de ruta.

Verificación del correo ​

Si el modelo de usuario implementa Illuminate\Contracts\Auth\MustVerifyEmail, el panel no se abre hasta que el correo está verificado. Mientras no lo está, la API responde 403 con email_verification_required: true y la SPA muestra la pantalla de verificación, con un botón para enviar el correo (limitado a tres por minuto).

php
final class User extends Authenticatable implements MustVerifyEmail
{
    // ...
}

El enlace del correo es una URL firmada y temporal. Caduca según auth.verification.expire (60 minutos por defecto), apunta a arrel.email.verify y, una vez verificado, redirige de nuevo al panel. Un usuario que no implementa MustVerifyEmail no pasa nunca por este paso.

Segundo factor ​

Arrel no lleva ninguna implementación de TOTP propia. Define el contrato Arrel\Auth\TwoFactorAuthenticator y tú enlazas la que quieras (un paquete de 2FA, una implementación propia sobre un secreto cifrado...).

php
namespace Arrel\Auth;

interface TwoFactorAuthenticator
{
    public function isEnabledFor(Authenticatable $user): bool;

    public function isRequiredFor(Authenticatable $user): bool;

    public function verify(Authenticatable $user, string $code): bool;

    public function newSecret(): string;

    public function qrCode(Authenticatable $user, string $secret): string;

    public function verifySetup(string $secret, string $code): bool;

    /** @return list<string> Los códigos de recuperación, para mostrarlos una sola vez. */
    public function enable(Authenticatable $user, string $secret): array;

    public function disable(Authenticatable $user): void;
}
MétodoCuándo se llama
isEnabledFor()En el inicio de sesión, para decidir si hay que pedir un código.
isRequiredFor()Para obligar a un usuario concreto a activarlo antes de entrar en el panel (por ejemplo, según su rol).
verify()Al validar el código del inicio de sesión. Debe aceptar también un código de recuperación.
newSecret(), qrCode()Al empezar la activación. qrCode() devuelve la imagen que la SPA muestra tal cual.
verifySetup()Al confirmar la activación, con el secreto todavía pendiente en la sesión.
enable()Una vez confirmado. Guarda el secreto y devuelve los códigos de recuperación.
disable()Al desactivarlo.

Para activarlo, enlaza tu implementación en el contenedor:

php
// AppServiceProvider::register()
$this->app->bind(TwoFactorAuthenticator::class, TotpAuthenticator::class);

Sin ningún enlace, el segundo factor no existe: no hay ningún paso adicional ni ninguna página de seguridad que usar.

Cómo lo ve el usuario ​

  1. En el inicio de sesión, si isEnabledFor() es cierto, la respuesta es { "two_factor": true } y la SPA pide el código.
  2. La página de seguridad (/{prefix}/{panel}/security) permite activarlo y desactivarlo. Al activarlo muestra el QR, pide un primer código y, una vez confirmado, muestra los códigos de recuperación una única vez.
  3. Si isRequiredFor() es cierto y el usuario todavía no lo ha activado, toda la API responde 403 con two_factor_setup_required: true y la SPA lo lleva a la página de seguridad. Los endpoints de la propia página de seguridad siguen accesibles.
  4. Un usuario para el que es obligatorio no puede desactivarlo: el endpoint responde 403 con arrel::auth.required_cannot_disable.

Los endpoints son GET y DELETE /arrel/api/two-factor, POST /arrel/api/two-factor/setup y POST /arrel/api/two-factor/confirm. La confirmación y la desactivación tienen un límite de 10 peticiones por minuto.

Middleware antes y después del usuario ​

config('arrel.middleware') se ejecuta antes de que Sanctum resuelva la sesión: es el lugar para identificar el tenant. config('arrel.authenticated_middleware') se ejecuta después de la verificación del correo y del segundo factor, con el usuario ya resuelto. Véase Configuración.

Notificaciones ​

La campana del panel lee las notificaciones de base de datos de Laravel del usuario autenticado. No hace falta nada específico de Arrel: basta con una notificación que use el canal database y guarde estas claves en data:

php
final class PostPublished extends Notification
{
    public function __construct(private readonly Post $post) {}

    public function via(object $notifiable): array
    {
        return ['database'];
    }

    public function toArray(object $notifiable): array
    {
        return [
            'title' => 'Post published',
            'body' => $this->post->title,
            'url' => "/arrel/admin/posts/{$this->post->id}",
        ];
    }
}
ClaveUso
titleTítulo de la entrada.
bodyTexto opcional bajo el título.
urlEnlace opcional que se abre al hacer clic en la entrada.

La campana muestra las 20 últimas notificaciones, el número de las no leídas, y permite marcar una o todas como leídas. Cada usuario solo ve y modifica las suyas.

Siguiente paso ​

Para decidir quién puede hacer qué dentro del panel, véase Seguridad y autorización.