{"id":259,"date":"2026-05-19T21:00:56","date_gmt":"2026-05-20T04:00:56","guid":{"rendered":"https:\/\/www.mariatech.com.mx\/blog\/?p=259"},"modified":"2026-05-19T21:00:57","modified_gmt":"2026-05-20T04:00:57","slug":"como-implementar-autenticacion-para-dos-tipos-de-usuarios-en-laravel-administradores-y-clientes","status":"publish","type":"post","link":"https:\/\/www.mariatech.com.mx\/blog\/laravel-php\/como-implementar-autenticacion-para-dos-tipos-de-usuarios-en-laravel-administradores-y-clientes\/","title":{"rendered":"C\u00f3mo implementar autenticaci\u00f3n para dos tipos de usuarios en Laravel: administradores y clientes"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">En proyectos web donde existen diferentes tipos de usuarios, una sola autenticaci\u00f3n puede quedarse corta. Un caso com\u00fan es cuando el sistema tiene un panel administrativo para colaboradores y, al mismo tiempo, una p\u00e1gina publica donde los clientes pueden iniciar sesi\u00f3n para consultar o gestionar su informaci\u00f3n.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En este art\u00edculo veremos c\u00f3mo estructurar en Laravel una autenticaci\u00f3n separada para dos tipos de usuarios: <strong>administradores<\/strong> y <strong>clientes<\/strong>. La idea es mantener una arquitectura limpia, segura y f\u00e1cil de mantener.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Contexto del proyecto<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">El escenario es el siguiente:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>El administrador accede desde una URL privada, por ejemplo: <code>\/admin<\/code>.<\/li>\n\n\n\n<li>Los clientes acceden desde el sitio p\u00fablico, por ejemplo: <code>\/<\/code>.<\/li>\n\n\n\n<li>Los administradores se almacenan en la tabla <code>users<\/code>.<\/li>\n\n\n\n<li>Los clientes se almacenan en la tabla <code>customers<\/code>.<\/li>\n\n\n\n<li>Cada secci\u00f3n usa vistas, layouts, assets y controladores separados.<\/li>\n\n\n\n<li>Se utiliza Laravel Breeze como punto de partida, pero se adapta la estructura para soportar dos autenticaciones independientes.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">La decisi\u00f3n principal fue no mezclar administradores y clientes en una misma tabla, ya que tienen responsabilidades, permisos y flujos completamente diferentes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Estructura recomendada del proyecto<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Una estructura limpia puede organizarse as\u00ed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>app\/\n\u251c\u2500\u2500 Http\/\n\u2502   \u251c\u2500\u2500 Controllers\/\n\u2502   \u2502   \u251c\u2500\u2500 Admin\/\n\u2502   \u2502   \u2502   \u251c\u2500\u2500 Auth\/\n\u2502   \u2502   \u2502   \u2514\u2500\u2500 DashboardController.php\n\u2502   \u2502   \u2502\n\u2502   \u2502   \u251c\u2500\u2500 Customer\/\n\u2502   \u2502   \u2502   \u251c\u2500\u2500 Auth\/\n\u2502   \u2502   \u2502   \u2514\u2500\u2500 AccountController.php\n\u2502   \u2502   \u2502\n\u2502   \u2502   \u2514\u2500\u2500 Controller.php\n\u2502   \u2502\n\u2502   \u251c\u2500\u2500 Requests\/\n\u2502   \u2502   \u251c\u2500\u2500 Admin\/\n\u2502   \u2502   \u2502   \u2514\u2500\u2500 Auth\/\n\u2502   \u2502   \u2502       \u2514\u2500\u2500 LoginRequest.php\n\u2502   \u2502   \u2502\n\u2502   \u2502   \u2514\u2500\u2500 Customer\/\n\u2502   \u2502       \u2514\u2500\u2500 Auth\/\n\u2502   \u2502           \u2514\u2500\u2500 LoginRequest.php\n\u2502\nresources\/\n\u251c\u2500\u2500 views\/\n\u2502   \u251c\u2500\u2500 admin\/\n\u2502   \u2502   \u251c\u2500\u2500 auth\/\n\u2502   \u2502   \u251c\u2500\u2500 layouts\/\n\u2502   \u2502   \u2514\u2500\u2500 dashboard\/\n\u2502   \u2502\n\u2502   \u2514\u2500\u2500 customer\/\n\u2502       \u251c\u2500\u2500 auth\/\n\u2502       \u251c\u2500\u2500 layouts\/\n\u2502       \u2514\u2500\u2500 account\/\n\u2502\nroutes\/\n\u251c\u2500\u2500 admin.php\n\u251c\u2500\u2500 customer.php\n\u251c\u2500\u2500 web.php\n\u2514\u2500\u2500 console.php\n\npublic\/\n\u2514\u2500\u2500 assets\/\n    \u251c\u2500\u2500 admin\/\n    \u2514\u2500\u2500 customer\/<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Esta separaci\u00f3n permite que cada secci\u00f3n tenga su propia l\u00f3gica, sus propios recursos visuales y sus propios middlewares.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Configuraci\u00f3n de guards y providers<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Laravel permite manejar m\u00faltiples sistemas de autenticaci\u00f3n mediante <strong>guards<\/strong> y <strong>providers<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En este caso usamos:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>web<\/code> para administradores.<\/li>\n\n\n\n<li><code>customer<\/code> para clientes.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">La configuraci\u00f3n se realiza en <code>config\/auth.php<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nuse App\\Models\\User;\nuse App\\Models\\Customer;\n\nreturn &#91;\n\n    'defaults' =&gt; &#91;\n        'guard' =&gt; env('AUTH_GUARD', 'web'),\n        'passwords' =&gt; env('AUTH_PASSWORD_BROKER', 'users'),\n    ],\n\n    'guards' =&gt; &#91;\n        'web' =&gt; &#91;\n            'driver' =&gt; 'session',\n            'provider' =&gt; 'users',\n        ],\n\n        'customer' =&gt; &#91;\n            'driver' =&gt; 'session',\n            'provider' =&gt; 'customers',\n        ],\n    ],\n\n    'providers' =&gt; &#91;\n        'users' =&gt; &#91;\n            'driver' =&gt; 'eloquent',\n            'model' =&gt; User::class,\n        ],\n\n        'customers' =&gt; &#91;\n            'driver' =&gt; 'eloquent',\n            'model' =&gt; Customer::class,\n        ],\n    ],\n\n    'passwords' =&gt; &#91;\n        'users' =&gt; &#91;\n            'provider' =&gt; 'users',\n            'table' =&gt; env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),\n            'expire' =&gt; 60,\n            'throttle' =&gt; 60,\n        ],\n\n        'customers' =&gt; &#91;\n            'provider' =&gt; 'customers',\n            'table' =&gt; env('CUSTOMER_AUTH_PASSWORD_RESET_TOKEN_TABLE', 'customer_password_reset_tokens'),\n            'expire' =&gt; 60,\n            'throttle' =&gt; 60,\n        ],\n    ],\n\n    'password_timeout' =&gt; env('AUTH_PASSWORD_TIMEOUT', 10800),\n\n];<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Un detalle importante es no usar la misma variable <code>AUTH_MODEL<\/code> para ambos providers, porque podr\u00eda provocar que los clientes intenten autenticarse con el modelo de usuarios administrativos.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Modelo Customer autenticable<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">El modelo de cliente no debe extender directamente de <code>Model<\/code>, sino de <code>Authenticatable<\/code>, igual que el modelo <code>User<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nnamespace App\\Models;\n\nuse Illuminate\\Foundation\\Auth\\User as Authenticatable;\nuse Illuminate\\Notifications\\Notifiable;\n\nclass Customer extends Authenticatable\n{\n    use Notifiable;\n\n    protected $guard = 'customer';\n\n    protected $fillable = &#91;\n        'name',\n        'last_name',\n        'phone',\n        'email',\n        'password',\n        'enabled',\n    ];\n\n    protected $hidden = &#91;\n        'password',\n        'remember_token',\n    ];\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Esto permite que Laravel pueda autenticar clientes usando el guard <code>customer<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Migraciones principales<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Para los clientes se puede crear una tabla independiente:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Schema::create('customers', function (Blueprint $table) {\n    $table-&gt;id();\n    $table-&gt;string('name');\n    $table-&gt;string('last_name');\n    $table-&gt;char('phone', 10)-&gt;nullable();\n    $table-&gt;string('email')-&gt;unique();\n    $table-&gt;timestamp('email_verified_at')-&gt;nullable();\n    $table-&gt;string('password');\n    $table-&gt;rememberToken();\n    $table-&gt;tinyInteger('enabled')-&gt;default(1);\n    $table-&gt;timestamps();\n});<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Tambi\u00e9n se puede manejar una tabla independiente para recuperaci\u00f3n de contrase\u00f1as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Schema::create('customer_password_reset_tokens', function (Blueprint $table) {\n    $table-&gt;string('email')-&gt;primary();\n    $table-&gt;string('token');\n    $table-&gt;timestamp('created_at')-&gt;nullable();\n});<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">En cuanto a sesiones, no es obligatorio crear una tabla diferente para clientes. Laravel usa la tabla <code>sessions<\/code> para guardar la sesi\u00f3n del navegador, no una sesi\u00f3n independiente por guard.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Rutas separadas<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Una buena pr\u00e1ctica es separar las rutas del administrador y del cliente.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ejemplo de <code>routes\/admin.php<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>use Illuminate\\Support\\Facades\\Route;\nuse App\\Http\\Controllers\\Admin\\Auth\\AuthenticatedSessionController;\nuse App\\Http\\Controllers\\Admin\\DashboardController;\n\nRoute::middleware('admin.guest')->group(function () {\n    Route::get('\/login', &#91;AuthenticatedSessionController::class, 'create'])\n        ->name('login');\n\n    Route::post('\/login', &#91;AuthenticatedSessionController::class, 'store'])\n        ->name('login.store');\n});\n\nRoute::middleware('admin.auth')->group(function () {\n    Route::get('\/dashboard', &#91;DashboardController::class, 'index'])\n        ->name('dashboard');\n\n    Route::post('\/logout', &#91;AuthenticatedSessionController::class, 'destroy'])\n        ->name('logout');\n});<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Ejemplo de <code>routes\/customer.php<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>use Illuminate\\Support\\Facades\\Route;\nuse App\\Http\\Controllers\\Customer\\Auth\\AuthenticatedSessionController;\nuse App\\Http\\Controllers\\Customer\\HomeController;\nuse App\\Http\\Controllers\\Customer\\AccountController;\n\nRoute::get('\/', &#91;HomeController::class, 'index'])\n    ->name('home');\n\nRoute::middleware('customer.guest')->group(function () {\n    Route::get('\/login', &#91;AuthenticatedSessionController::class, 'create'])\n        ->name('login');\n\n    Route::post('\/login', &#91;AuthenticatedSessionController::class, 'store'])\n        ->name('login.store');\n});\n\nRoute::middleware('customer.auth')->group(function () {\n    Route::get('\/mi-cuenta', &#91;AccountController::class, 'index'])\n        ->name('account');\n\n    Route::post('\/logout', &#91;AuthenticatedSessionController::class, 'destroy'])\n        ->name('logout');\n});<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Cargar rutas desde bootstrap\/app.php<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">En Laravel moderno, las rutas adicionales pueden registrarse desde <code>bootstrap\/app.php<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>use Illuminate\\Support\\Facades\\Route;\n\n->withRouting(\n    web: __DIR__.'\/..\/routes\/web.php',\n    commands: __DIR__.'\/..\/routes\/console.php',\n    then: function () {\n        Route::middleware('web')\n            ->prefix('admin')\n            ->name('admin.')\n            ->group(base_path('routes\/admin.php'));\n\n        Route::middleware('web')\n            ->name('customer.')\n            ->group(base_path('routes\/customer.php'));\n    },\n)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Con esta configuraci\u00f3n se obtienen rutas como:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>\/admin\/login<\/code> \u2192 <code>admin.login<\/code><\/li>\n\n\n\n<li><code>\/admin\/dashboard<\/code> \u2192 <code>admin.dashboard<\/code><\/li>\n\n\n\n<li><code>\/login<\/code> \u2192 <code>customer.login<\/code><\/li>\n\n\n\n<li><code>\/mi-cuenta<\/code> \u2192 <code>customer.account<\/code><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Middlewares propios por tipo de usuario<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Para evitar l\u00f3gica condicional dentro de <code>bootstrap\/app.php<\/code>, se pueden crear middlewares espec\u00edficos para cada secci\u00f3n.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Por ejemplo:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>admin.auth<\/code>: valida que el usuario admin est\u00e9 autenticado y activo.<\/li>\n\n\n\n<li><code>admin.guest<\/code>: evita que un admin autenticado vuelva al login.<\/li>\n\n\n\n<li><code>customer.auth<\/code>: valida que el cliente est\u00e9 autenticado y activo.<\/li>\n\n\n\n<li><code>customer.guest<\/code>: evita que un cliente autenticado vuelva al login.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Middleware de administrador autenticado:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nnamespace App\\Http\\Middleware\\Admin;\n\nuse Closure;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Symfony\\Component\\HttpFoundation\\Response;\n\nclass EnsureAdminIsAuthenticated\n{\n    public function handle(Request $request, Closure $next): Response\n    {\n        if (! Auth::guard('web')-&gt;check()) {\n            return redirect()-&gt;route('admin.login');\n        }\n\n        $user = Auth::guard('web')-&gt;user();\n\n        if (! $user-&gt;enabled) {\n            Auth::guard('web')-&gt;logout();\n\n            $request-&gt;session()-&gt;invalidate();\n            $request-&gt;session()-&gt;regenerateToken();\n\n            return redirect()\n                -&gt;route('admin.login')\n                -&gt;withErrors(&#91;\n                    'email' =&gt; 'Tu cuenta se encuentra deshabilitada.',\n                ]);\n        }\n\n        return $next($request);\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Middleware de cliente autenticado:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nnamespace App\\Http\\Middleware\\Customer;\n\nuse Closure;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Symfony\\Component\\HttpFoundation\\Response;\n\nclass EnsureCustomerIsAuthenticated\n{\n    public function handle(Request $request, Closure $next): Response\n    {\n        if (! Auth::guard('customer')-&gt;check()) {\n            return redirect()-&gt;route('customer.login');\n        }\n\n        $customer = Auth::guard('customer')-&gt;user();\n\n        if (! $customer-&gt;enabled) {\n            Auth::guard('customer')-&gt;logout();\n\n            $request-&gt;session()-&gt;invalidate();\n            $request-&gt;session()-&gt;regenerateToken();\n\n            return redirect()\n                -&gt;route('customer.login')\n                -&gt;withErrors(&#91;\n                    'email' =&gt; 'Tu cuenta se encuentra deshabilitada.',\n                ]);\n        }\n\n        return $next($request);\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Despu\u00e9s se registran los alias de middleware en <code>bootstrap\/app.php<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>use Illuminate\\Foundation\\Configuration\\Middleware;\nuse App\\Http\\Middleware\\Admin\\EnsureAdminIsAuthenticated;\nuse App\\Http\\Middleware\\Admin\\RedirectIfAdminAuthenticated;\nuse App\\Http\\Middleware\\Customer\\EnsureCustomerIsAuthenticated;\nuse App\\Http\\Middleware\\Customer\\RedirectIfCustomerAuthenticated;\n\n->withMiddleware(function (Middleware $middleware): void {\n    $middleware->alias(&#91;\n        'admin.auth' => EnsureAdminIsAuthenticated::class,\n        'admin.guest' => RedirectIfAdminAuthenticated::class,\n\n        'customer.auth' => EnsureCustomerIsAuthenticated::class,\n        'customer.guest' => RedirectIfCustomerAuthenticated::class,\n    ]);\n})<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">LoginRequest para clientes<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Uno de los errores m\u00e1s comunes al trabajar con m\u00faltiples guards es usar <code>Auth::attempt()<\/code> sin especificar guard. Cuando se hace eso, Laravel utiliza el guard por defecto, normalmente <code>web<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Para el login de clientes debe usarse:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Auth::guard('customer')-&gt;attempt($credentials, $this-&gt;boolean('remember'))<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Ejemplo:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public function authenticate(): void\n{\n    $this-&gt;ensureIsNotRateLimited();\n\n    $credentials = $this-&gt;only('email', 'password');\n    $credentials&#91;'enabled'] = 1;\n\n    if (! Auth::guard('customer')-&gt;attempt($credentials, $this-&gt;boolean('remember'))) {\n        RateLimiter::hit($this-&gt;throttleKey());\n\n        throw ValidationException::withMessages(&#91;\n            'email' =&gt; trans('auth.failed'),\n        ]);\n    }\n\n    Auth::guard('web')-&gt;logout();\n\n    RateLimiter::clear($this-&gt;throttleKey());\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">En este ejemplo, despu\u00e9s de iniciar sesi\u00f3n como cliente, se cierra cualquier sesi\u00f3n activa del administrador en el mismo navegador.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">LoginRequest para administradores<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Para el administrador se hace lo mismo, pero usando el guard <code>web<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public function authenticate(): void\n{\n    $this-&gt;ensureIsNotRateLimited();\n\n    $credentials = $this-&gt;only('email', 'password');\n    $credentials&#91;'enabled'] = 1;\n\n    if (! Auth::guard('web')-&gt;attempt($credentials, $this-&gt;boolean('remember'))) {\n        RateLimiter::hit($this-&gt;throttleKey());\n\n        throw ValidationException::withMessages(&#91;\n            'email' =&gt; trans('auth.failed'),\n        ]);\n    }\n\n    Auth::guard('customer')-&gt;logout();\n\n    RateLimiter::clear($this-&gt;throttleKey());\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">De esta manera se evita que el mismo navegador mantenga una sesi\u00f3n de administrador y una sesi\u00f3n de cliente al mismo tiempo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Uso correcto en Blade<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Otro detalle importante es que la directiva <code>@auth<\/code> usa el guard por defecto si no se especifica uno. Por eso, en vistas de cliente se debe indicar expl\u00edcitamente el guard.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Para clientes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@auth('customer')\n    Hola, {{ auth('customer')->user()->name }}\n@endauth\n\n@guest('customer')\n    &lt;a href=\"{{ route('customer.login') }}\">Iniciar sesi\u00f3n&lt;\/a>\n@endguest<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Para administradores:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@auth('web')\n    Hola, {{ auth('web')->user()->name }}\n@endauth\n\n@guest('web')\n    &lt;a href=\"{{ route('admin.login') }}\">Iniciar sesi\u00f3n&lt;\/a>\n@endguest<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Sesiones en base de datos<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Cuando se usa <code>SESSION_DRIVER=database<\/code>, Laravel guarda la sesi\u00f3n del navegador en la tabla <code>sessions<\/code>. Es importante entender que no se crea una sesi\u00f3n independiente por guard.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Si se inicia sesi\u00f3n como administrador y despu\u00e9s como cliente en el mismo navegador, Laravel puede seguir usando el mismo registro de sesi\u00f3n. Lo importante es que el guard correcto est\u00e9 autenticado y el otro haya sido cerrado.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Para validar:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>auth('web')-&gt;check();   \/\/ Admin\nauth('customer')-&gt;check(); \/\/ Cliente<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Tambi\u00e9n es normal que el registro en la tabla <code>sessions<\/code> permanezca por un tiempo aunque el usuario haya cerrado sesi\u00f3n. Laravel limpia las sesiones expiradas seg\u00fan su configuraci\u00f3n de expiraci\u00f3n.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Extras<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Assets separados con Vite<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Si cada secci\u00f3n utiliza un template diferente, tambi\u00e9n conviene separar los assets.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>resources\/\n\u251c\u2500\u2500 admin\/\n\u2502   \u251c\u2500\u2500 css\/\n\u2502   \u2502   \u2514\u2500\u2500 app.css\n\u2502   \u2514\u2500\u2500 js\/\n\u2502       \u2514\u2500\u2500 app.js\n\u2502\n\u2514\u2500\u2500 customer\/\n    \u251c\u2500\u2500 css\/\n    \u2502   \u2514\u2500\u2500 app.css\n    \u2514\u2500\u2500 js\/\n        \u2514\u2500\u2500 app.js<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Ejemplo de <code>vite.config.js<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { defineConfig } from 'vite';\nimport laravel from 'laravel-vite-plugin';\n\nexport default defineConfig({\n    plugins: &#91;\n        laravel({\n            input: &#91;\n                'resources\/admin\/css\/app.css',\n                'resources\/admin\/js\/app.js',\n\n                'resources\/customer\/css\/app.css',\n                'resources\/customer\/js\/app.js',\n            ],\n            refresh: true,\n        }),\n    ],\n});<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">En el layout de administrador:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@vite(&#91;\n    'resources\/admin\/css\/app.css',\n    'resources\/admin\/js\/app.js'\n])<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">En el layout de cliente:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@vite(&#91;\n    'resources\/customer\/css\/app.css',\n    'resources\/customer\/js\/app.js'\n])<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusi\u00f3n<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Implementar autenticaci\u00f3n para dos tipos de usuarios en Laravel requiere separar responsabilidades desde el inicio. La clave est\u00e1 en no mezclar modelos, guards, rutas ni vistas.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Una arquitectura limpia para este caso ser\u00eda:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>users<\/code> para administradores.<\/li>\n\n\n\n<li><code>customers<\/code> para clientes.<\/li>\n\n\n\n<li><code>web<\/code> como guard de administradores.<\/li>\n\n\n\n<li><code>customer<\/code> como guard de clientes.<\/li>\n\n\n\n<li><code>resources\/views\/admin<\/code> para el panel administrativo.<\/li>\n\n\n\n<li><code>resources\/views\/customer<\/code> para el portal p\u00fablico.<\/li>\n\n\n\n<li><code>routes\/admin.php<\/code> y <code>routes\/customer.php<\/code> para separar rutas.<\/li>\n\n\n\n<li>Middlewares propios para controlar accesos y redirecciones.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Esta estructura evita confusiones, mejora la seguridad y permite que el proyecto crezca de forma ordenada.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En sistemas donde existen usuarios internos y clientes finales, separar la autenticaci\u00f3n no solo es una buena pr\u00e1ctica t\u00e9cnica: tambi\u00e9n facilita el mantenimiento, las pruebas y la evoluci\u00f3n del proyecto.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>En este art\u00edculo veremos c\u00f3mo estructurar en Laravel una autenticaci\u00f3n separada para dos tipos de usuarios: administradores y clientes&#8230;<\/p>\n","protected":false},"author":1,"featured_media":260,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"class_list":["post-259","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-laravel-php"],"_links":{"self":[{"href":"https:\/\/www.mariatech.com.mx\/blog\/wp-json\/wp\/v2\/posts\/259","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mariatech.com.mx\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mariatech.com.mx\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mariatech.com.mx\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mariatech.com.mx\/blog\/wp-json\/wp\/v2\/comments?post=259"}],"version-history":[{"count":0,"href":"https:\/\/www.mariatech.com.mx\/blog\/wp-json\/wp\/v2\/posts\/259\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mariatech.com.mx\/blog\/wp-json\/wp\/v2\/media\/260"}],"wp:attachment":[{"href":"https:\/\/www.mariatech.com.mx\/blog\/wp-json\/wp\/v2\/media?parent=259"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mariatech.com.mx\/blog\/wp-json\/wp\/v2\/categories?post=259"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mariatech.com.mx\/blog\/wp-json\/wp\/v2\/tags?post=259"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}