# Control de usuarios

Laravel incluye una serie de métodos y clases que harán que la implementación del control de usuarios sea muy rápida y sencilla. De hecho, casi todo el trabajo ya está hecho, solo tendremos que indicar donde queremos utilizarlo y algunos pequeños detalles de configuración.

Por defecto, al crear un nuevo proyecto de Laravel, ya se incluye todo lo necesario:

* La configuración predeterminada en `config/auth.php`.
* La migración para la base de datos de la tabla de usuarios con todos los campos necesarios.
* El modelo de datos de usuario (`User.php`) dentro de la carpeta `app` con toda la implementación necesaria.&#x20;
* Los controladores para gestionar todas las acciones relacionadas con el control de usuarios (dentro de `App\Http\Controllers\Auth`).&#x20;

Además de esto tendremos que ejecutar el siguiente comando para generar las rutas y vistas necesarias para realizar el login, registro y para recuperar la contraseña:

```bash
php artisan make:auth
```

En los siguientes apartados vamos a ver en detalle cada uno de estos puntos, desde la configuración hasta los módulos, rutas y vistas por los que está compuesto. En las últimas secciones revisaremos también cómo utilizar este sistema para proteger nuestro sitio web.

## Configuración inicial

La **configuración** del sistema de autenticación se puede encontrar en el fichero `config/auth.php`, el cual contiene varias opciones (bien documentadas) que nos permitirán, por ejemplo: cambiar el sistema de autenticación (que por defecto es a través de Eloquent), cambiar el modelo de datos usado para los usuarios (por defecto será `User`) y cambiar la tabla de usuarios (que por defecto será `users`). Si vamos a utilizar estos valores no será necesario que realicemos ningún cambio.

La **migración** de la tabla de usuarios (llamada `users`) también está incluida (ver carpeta `database/migrations`). Por defecto incluye todos los campos necesarios (ver el código siguiente), pero si necesitamos alguno más lo podemos añadir para guardar por ejemplo la dirección o el teléfono del usuario. A continuación se incluye el código de la función `up` de la migración:

```php
Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('email')->unique();
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});
```

Como se puede ver el nombre de la tabla es `users`, con un índice `id` autoincremental, y los campos de `name`, `email`, `password`, donde el campo _email_ se establece como único para que no se puedan almacenar emails repetidos. Además se añaden los _timestamps_ que usa Eloquent para almacenar automáticamente la fecha de registro y actualización, y el campo `remember_token` para recordar la sesión del usuario.

En la carpeta `app` se encuentra el **modelo de datos** (llamado `User.php`) para trabajar con los usuarios. Esta clase ya incluye toda la implementación necesaria y por defecto no tendremos que modificar nada. Pero si queremos podemos modificar esta clase para añadirle más métodos o relaciones con otras tablas, etc.

Laravel también incluye varios **controladores** (`LoginController`, `RegisterController`, `ResetPasswordController` y `ForgotPasswordController`) para la autenticación de usuarios, los cuales los puedes encontrar en el espacio de nombres `App\Http\Controllers\Auth` (y en la misma carpeta). `LoginController` y `RegisterController` incluyen métodos para ayudarnos en el proceso de autenticación, registro y cierre de sesión; mientras que `ResetPasswordController` y `ForgotPasswordController` contienen la lógica para ayudarnos en el proceso de restaurar una contraseña. Para la mayoría de aplicaciones con estos métodos será suficiente y no tendremos que añadir nada más.

Lo único que falta por añadir y configurar correctamente para que todo funcione son las rutas y las vistas, que como hemos mencionado en la introducción se generan mediante el siguiente comando:

```bash
php artisan make:auth
```

En las siguientes secciones vamos a ver las rutas y vistas que se generan y cómo se tienen que utilizar.

### Rutas

Por defecto Laravel no incluye las rutas para el control de usuarios, para generarlas tenemos que ejecutar el comando `php artisan make:auth`. Este comando nos añadirá las siguientes líneas al fichero `routes/web.php`:

```php
Auth::routes();
Route::get('/home', 'HomeController@index');
```

La primera línea (`Auth::routes`) es la que añade todas las rutas para el _login_, _logout_, registro y para recuperar la contraseña. La segunda entrada añade la ruta `home` que apunta al controlador `HomeController` (el cual se habrá creado también), esta ruta es la que se utiliza para redirigir a los usuarios cuando realicen el login correctamente. En la siguiente tabla se puede ver un resumen de todas las rutas añadidas:

| Method | Url                    | Acción                                       | Filtros   |
| ------ | ---------------------- | -------------------------------------------- | --------- |
| GET    | login                  | LoginController@showLoginForm                | web,guest |
| POST   | login                  | LoginController@login                        | web,guest |
| POST   | logout                 | LoginController@logout                       | web       |
| GET    | register               | RegisterController@showRegistrationForm      | web,guest |
| POST   | register               | RegisterController@register                  | web,guest |
| POST   | password/email         | ForgotPasswordController@sendResetLinkEmail  | web,guest |
| GET    | password/reset         | ForgotPasswordController@showLinkRequestForm | web,guest |
| POST   | password/reset         | ResetPasswordController@reset                | web,guest |
| GET    | password/reset/{token} | ResetPasswordController@showResetForm        | web,guest |
| GET    | home                   | HomeController@index                         | web,auth  |

Como se puede ver estas rutas ya están enlazadas con los controladores y métodos que incorpora el propio Laravel. Al acceder a la ruta `login` por GET se llamará a `LoginController@showLoginForm` el cual se encargará de mostrar el formulario de login, y lo mismo para la ruta `register` tipo GET para el registro. Las rutas `login` y `register` por POST se encargarán de procesar los datos enviados por los formularios. Al acceder a la ruta `logout` por POST se cerrará la sesión. Además hay cuatro rutas que se utilizan para recuperar la contraseña del usuario: al acceder a `password/reset` por GET se mostrará el formulario para que escribamos nuestra dirección de correo y enviarnos el _link_ para restablecer la contraseña (lo cual lo gestionará la petición a `password/email` mediante POST). Al pulsar sobre el _link_ enviado al correo se accederá a `password/reset/{token}` por GET con el _token_ generado, esto nos mostrará el formulario para que establezcamos una nueva contraseña y finalmente lo enviemos a `password/reset` mediante POST.

> Las direcciones URLs generadas son fijas, si queremos modificarlas lo más sencillo es que comentemos la línea `Auth::routes()` que se ha añadido al fichero de rutas y que las escribamos nosotros manualmente, copiando lo mismo que generaría `Auth::routes()` pero cambiando únicamente las URLs.

### Vistas

Al ejecutar el comando `php artisan make:auth` también se generarán todas las vistas necesarias para realizar el _login_, registro y para recuperar la contraseña. Todas estas vistas las podremos encontrar en la carpeta `resources/views/auth` con los nombres `login.blade.php` para el formulario de _login_, `register.blade.php` para el formulario de registro, `passwords/email.blade.php` para el formulario de recuperar contraseña y `passwords/reset.blade.php` para el formulario de restaurar la contraseña. Estos nombres y rutas son obligatorios ya que los controladores que incluye Laravel accederán a ellos, por lo que no deberemos cambiarlos.

Si abrimos cualquiera de ellos veremos como utiliza el sistema de plantillas de Blade, en todos ellos hereda del layout `layouts/app.blade.php` mediante la directiva `@extends('layouts.app')` y rellena el contenido de su zona central `content`. Esta plantilla de _layout_ establece la estructura básica, carga la hoja de estilo y Javascript de Bootstrap, y añade el menú principal con botones para acceder al _login_ y registro. Cada uno de los formularios está enlazado con la ruta correspondiente, y además incluye código para mostrar los errores generados y volver a rellenar los campos tras un error con el texto que haya escrito el usuario.

A modo de ejemplo se incluye el código para la vista del formulario de _login_:

```markup
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">Login</div>
                <div class="panel-body">
                    <form class="form-horizontal" role="form" method="POST" action="{{ url('/login') }}">
                        {{ csrf_field() }}
                        <div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
                            <label for="email" class="col-md-4 control-label">E-Mail Address</label>
                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control" name="email" value="{{ old('email') }}" required autofocus>
                                @if ($errors->has('email'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('email') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>
                        <div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
                            <label for="password" class="col-md-4 control-label">Password</label>
                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control" name="password" required>
                                @if ($errors->has('password'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('password') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>
                        <div class="form-group">
                            <div class="col-md-6 col-md-offset-4">
                                <div class="checkbox">
                                    <label>
                                        <input type="checkbox" name="remember"> Remember Me
                                    </label>
                                </div>
                            </div>
                        </div>
                        <div class="form-group">
                            <div class="col-md-8 col-md-offset-4">
                                <button type="submit" class="btn btn-primary">
                                    Login
                                </button>
                                <a class="btn btn-link" href="{{ url('/password/reset') }}">
                                    Forgot Your Password?
                                </a>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
```

Si lo deseamos podemos modificar el contenido y diseño de cualquier vista, así como del _layout_, lo único que tenemos que mantener igual es la URL a la que se envía el formulario y los nombres de cada uno de los _inputs_ del formulario.

## Autenticación de un usuario

Una vez configurado todo el sistema, añadidas las rutas y las vistas para realizar el control de usuarios ya podemos utilizarlo. Si accedemos a la ruta `login` nos aparecerá la vista con el formulario de login, solicitando nuestro email y contraseña para acceder. El campo tipo _checkbox_ llamado "_remember_" nos permitirá indicar si deseamos que la sesión permanezca abierta hasta que se cierre manualmente. Es decir, aunque se cierre el navegador y pasen varios días el usuario seguiría estando autorizado.

Si los datos introducidos son correctos se creará la sesión del usuario y se le redirigirá a la ruta "`/home`". Si queremos cambiar esta ruta tenemos que definir la propiedad `redirectTo` en el controlador `LoginController`, por ejemplo:

```php
protected $redirectTo = '/';
```

Además podemos definir esta propiedad en `RegisterController` y `ResetPasswordController` para cambiar la URL de redirección después del registro y después de restablecer la contraseña, respectivamente.

## Registro de un usuario

Si accedemos a la ruta `register` nos aparecerá la vista con el formulario de registro, solicitándonos los campos nombre, _email_ y contraseña. Al pulsar el botón de envío del formulario se llamará a la ruta `register` por POST y se almacenará el nuevo usuario en la base de datos.

Si no hemos añadido ningún campo más en la migración no tendremos que configurar nada más. Sin embargo si hemos añadido algún campo más a la tabla de usuarios tendremos que actualizar dos métodos del controlador `RegisterController`: `validator` y `create`. En el método `validator` simplemente tendremos que añadir dicho campo al array de validaciones (solo en el caso que necesitemos validarlo). Y en el método `create` tendremos que añadir los campos adicionales que deseemos almacenar. El código de este método es el siguiente:

```php
protected function create(array $data) {
    return User::create([
        'name' => $data['name'],
        'email' => $data['email'],
        'phone' => $data['phone'],     // Campo añadido
        'password' => bcrypt($data['password']),
    ]);
}
```

Como podemos ver utiliza el modelo de datos `User` para crear el usuario y almacenar las variables que recibe en el array de datos `$data`. En este array de datos nos llegarán todos los valores de los campos del formulario, por lo tanto, si añadimos más campos al formulario y a la tabla de usuarios simplemente tendremos que añadirlos también en este método.

Es importante destacar que la contraseña se cifra usando el método `bcrypt`, por lo tanto las contraseñas se almacenaran cifradas en la base de datos. Este cifrado se basa en la clave _hash_ que se general al crear un nuevo proyecto de Laravel (ver capítulo de "Instalación") y que se encuentra almacenada en el fichero `.env` en la variable `APP_KEY`. Es importante que este _hash_ se haya establecido al inicio (que no esté vacío o se uno por defecto) y que además **no se modifique** una vez la aplicación se suba a producción.

### Registro manual de un usuario

Si queremos añadir un usuario manualmente lo podemos hacer de forma normal usando el modelo `User` de `Eloquent`, con la única precaución de cifrar la contraseña que se va a almacenar. A continuación se incluye un ejemplo de una función que crea un nuevo usuario a partir de los parámetros de entrada recibidos de un formulario:

```php
public function store(Request $request) {
    $user = new User;
    $user->name = $request->input('name');
    $user->email = $request->input('email');
    $user->password = bcrypt( $request->input('password') );
    $user->save();
}
```

## Acceder a los datos del usuario autenticado

Una vez que el usuario está autenticado podemos acceder a los datos del mismo a través del método `Auth::user()`, por ejemplo:

```php
user = Auth::user();
```

Este método nos devolverá `null` en caso de que no esté autenticado. Si estamos seguros de que el usuario está autenticado (porque estamos en una ruta protegida) podremos acceder directamente a sus propiedades:

```php
$email = Auth::user()->email;
```

> Importante: para utilizar la clase `Auth` tenemos que añadir el espacio de nombres `use Illuminate\Support\Facades\Auth;`, de otra forma nos aparecerá un error indicando que no puede encontrar la clase.

El usuario también se inyecta en los parámetros de entrada de la petición (en la clase `Request`). Por lo tanto, si en un método de un controlador usamos la inyección de dependencias también podremos acceder a los datos del usuario:

```php
use Illuminate\Http\Request;

class ProfileController extends Controller {
    public function updateProfile(Request $request) {
        if ($request->user()) {
            $email = $request->user()->email;
        }
    }
}
```

## Cerrar la sesión

Si accedemos a la ruta `logout` por POST se cerrará la sesión y se redirigirá a la ruta `/`. Todo esto lo hará automáticamente el método `logout` del controlador `LoginController`.

Para cerrar manualmente la sesión del usuario actualmente autenticado tenemos que utilizar el método:

```php
Auth::logout();
```

Posteriormente podremos hacer una redirección a una página principal para usuarios no autenticados.

> Importante: para utilizar la clase `Auth` tenemos que añadir el espacio de nombres `use Illuminate\Support\Facades\Auth;`, de otra forma nos aparecerá un error indicando que no puede encontrar la clase.

## Comprobar si un usuario está autenticado

Para comprobar si el usuario actual se ha autenticado en la aplicación podemos utilizar el método `Auth::check()` de la forma:

```php
if (Auth::check()) {
    // El usuario está correctamente autenticado
}
```

Sin embargo, lo recomendable es utilizar _Middleware_ (como veremos a continuación) para realizar esta comprobación antes de permitir el acceso a determinadas rutas.

> Importante: Recuerda que para utilizar la clase `Auth` tenemos que añadir el espacio de nombres `use Illuminate\Support\Facades\Auth;`, de otra forma nos aparecerá un error indicando que no puede encontrar la clase.

## Proteger rutas

El sistema de autenticación de Laravel también incorpora una serie de filtros o _Middleware_ (ver carpeta `app/Http/Middleware` y el fichero `app/Http/Kernel.php`) para comprobar que el usuario que accede a una determinada ruta o grupo de rutas esté autenticado. En concreto para proteger el acceso a rutas y solo permitir su visualización por usuarios correctamente autenticados usaremos el _middleware_ `\Illuminate\Auth\Middleware\Authenticate.php` cuyo alias es `auth`. Para utilizar este _middleware_ tenemos que editar el fichero `routes/web.php` y modificar las rutas que queramos proteger, por ejemplo:

```php
// Para proteger una clausula:
Route::get('admin/catalog', function() {
    // Solo se permite el acceso a usuarios autenticados
})->middleware('auth');

// Para proteger una acción de un controlador:
Route::get('profile', 'ProfileController@show')->middleware('auth');
```

Si el usuario que accede no está validado se generará una excepción que le redirigirá a la ruta `login`. Si deseamos cambiar esta dirección tendremos que modificar el método que gestiona la excepción, el cual lo podremos encontrar en `App\Exceptions\Handler@unauthenticated`.

Si deseamos proteger el acceso a toda una zona de nuestro sitio web (por ejemplo la parte de administración o la gestión de un recurso), lo más cómodo es crear un grupo con todas esas rutas que utilice el _middleware_ `auth`, por ejemplo:

```php
Route::group(['middleware' => 'auth'], function() {
    Route::get('catalog',        'CatalogController@getIndex');
    Route::get('catalog/create', 'CatalogController@getCreate');
    // ...
});
```

Si lo deseamos también podemos especificar el uso de este _middleware_ desde el constructor del controlador:

```php
public function __construct() {
    $this->middleware('auth');
}
```

Sin embargo, lo más recomendable es indicarlo desde el fichero de rutas pues así tendremos todas las rutas y filtros centralizados en un único fichero.
