Laravel es un framework de PHP increible, pero tal vez te has preguntado como usarlo de Backend para que otras aplicaciones puedan obtener información de nuestra aplicación, o simplemente, deseas crear un Frontend que consuma los recursos de la API REST.
De ahí que surja la duda, ¿Cómo hago para autenticar los usuarios?
La solución es JWT.
Si todavía no conoces como funciona Laravel o qué es Laravel, te recomiendo ver el Curso de PHP con Laravel.
JWT te permite retornar un token de autenticación que te identificará como usuario del sistema, que se guardará del lado del navegador (localStorage, sessionStorage, cookies, Redux, etc…).
Una vez que ya entendiste la idea, manos a la obra.
<h1>Creando nuestro proyecto</h1>NOTA: No es necesario realizar estos pasos si tu proyecto de Laravel ya está creado.
Lo primero que debemos hacer es tener instalado el gestor de dependencias de PHP composer.
Aquí te dejo un link para que puedas instalarlo sin problemas, en la versión de Ubuntu.
Para otras sistemas operativos, te recomiendo la página oficial de Composer
Una vez lo tengamos instalado, comprobamos que funcione correctamente, escribiendo en nuestra terminal:
composer --version
Tendrás un resultado similar a este:
Composerversion 1.10.15 2020-10-13 15:59:09
Si no tienes instalado Laravel, lo instalamos de esta forma en Ubuntu:
composerglobalrequire laravel/installer
Para otros sistemas operativos, les recomiendo leer el Manual de instalación de Laravel
Una vez, tengamos nuestras dependencias listas, nos movemos a nuestro directorio donde vamos a crear una carpeta para guardar nuestro proyecto. y ejecutamos el siguiente comando para crear nuestro proyecto de Laravel:
composer create-project--prefer-dist laravel/laravel nombre-proyecto
Una vez creado nuestro proyecto, accedemos a el:
cd nombre-proyecto/
Ahora vamos a probar si funciona la aplicación correctamente, iniciando el servidor de desarrollo:
php artisan serv
Nos mostrará un enlace a nuestro servidor local, algo parecido a esto:
Starting Laravel development server:http://127.0.0.1:8000
Copiamos el URL en nuestro navegador y nos debe mostrar esta vista:
Y ya estaría configurado nuestro proyecto correctamente.
<h1>Generando nuestra base de datos</h1>Es necesario configurar nuestras variables de entorno de conexión a nuestra base de datos en el archivo .env, para esto puedes usar tu editor de texto de confianza (Vim, Nano, VS Code, Sublime Text, etc…)
Debemos tener nuestra base de datos creada sin tablas para ejecutar la migración por defecto de Laravel, que permite crear la tabla users
php artisan migrate
Si quieres personalizar tu tabla usuarios, puedes personalizar esto en config/auth.php y app/Models/User.php
<h1>Instalando y configurando JWT</h1>Vamos a instalar las dependencias de JWT:
composer require tymon/jwt-auth:dev-develop --prefer-source
Debes incluir la siguiente línea en el archivo config/app.php dentro del array de providers
Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
En el mismo archivo, en el array aliases agregamos las siguientes líneas:
'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class,
Comprobamos que funcione correctamente con el siguiente comando:
phpartisanjwt:secret
Ahora en la clase User, implementamos los siguientes 2 métodos:
publicfunctiongetJWTIdentifier(){
return $this->getKey();
}
publicfunctiongetJWTCustomClaims(){
return [];
}
Es necesario que esta clase implemente JWTSubject
use Tymon\JWTAuth\Contracts\JWTSubject;
classUserextendsAuthenticatableimplementsJWTSubject{
Crearemos un middleware para JWT con el siguiente comando:
phpartisanmake:middlewareJwtMiddleware
Modificamos el nuevo Middleware con las siguientes líneas de código:
<?phpnamespaceApp\Http\Middleware;
useClosure;
useJWTAuth;
useException;
useTymon\JWTAuth\Http\Middleware\BaseMiddleware;
classJwtMiddlewareextendsBaseMiddleware{
publicfunctionhandle($request, Closure $next){
try {
$user = JWTAuth::parseToken()->authenticate();
} catch (Exception $e) {
if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenInvalidException){
return response()->json(['status' => 'Token is Invalid']);
}elseif ($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException){
return response()->json(['status' => 'Token is Expired']);
}else{
return response()->json(['status' => 'Authorization Token not found']);
}
}
return $next($request);
}
}
Para finalizar este paso, añadimos el nuevo Middleware al Kernel, agregando la siguiente línea al archivo en app/http/Kernel.php en routeMiddleware:
'jwt.verify' => \App\Http\Middleware\JwtMiddleware::class,
<h1>Configurando métodos y rutas</h1>
Ahora procedemos a crear UserController para crear los métodos de registro y autenticación:
phpartisanmake:controllerUserController
Una vez creado en la app/Http/Controllers, procedemos a modificarlo para que quede de la siguiente forma:
<?phpnamespaceApp\Http\Controllers;
useApp\Models\User;
useIlluminate\Http\Request;
useIlluminate\Support\Facades\Hash;
useIlluminate\Support\Facades\Validator;
useJWTAuth;
useTymon\JWTAuth\Exceptions\JWTException;
classUserControllerextendsController{
publicfunctionauthenticate(Request $request){
$credentials = $request->only('email', 'password');
try {
if (! $token = JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'invalid_credentials'], 400);
}
} catch (JWTException $e) {
return response()->json(['error' => 'could_not_create_token'], 500);
}
return response()->json(compact('token'));
}
publicfunctiongetAuthenticatedUser(){
try {
if (!$user = JWTAuth::parseToken()->authenticate()) {
return response()->json(['user_not_found'], 404);
}
} catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
return response()->json(['token_expired'], $e->getStatusCode());
} catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
return response()->json(['token_invalid'], $e->getStatusCode());
} catch (Tymon\JWTAuth\Exceptions\JWTException $e) {
return response()->json(['token_absent'], $e->getStatusCode());
}
return response()->json(compact('user'));
}
publicfunctionregister(Request $request){
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
]);
if($validator->fails()){
return response()->json($validator->errors()->toJson(), 400);
}
$user = User::create([
'name' => $request->get('name'),
'email' => $request->get('email'),
'password' => Hash::make($request->get('password')),
]);
$token = JWTAuth::fromUser($user);
return response()->json(compact('user','token'),201);
}
}
Lo siguiente es indicarle a nuestro aplicación cuales son las rutas a las que se accederán para registrarse e iniciar sesión. Para esto modificaremos el archivo routes/api.php.
Debemos comentar las siguientes lineas:
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
// Route::middleware('auth:api')->get('/user', function (Request $request) {
// return $request->user();
// });
Y escribir las siguientes líneas:
Route::post('register', 'App\Http\Controllers\UserController@register');
Route::post('login', 'App\Http\Controllers\UserController@authenticate');
Creamos un group para indicar cuales son las rutas que necesitan autenticación:
Route::group(['middleware' => ['jwt.verify']], function() {
Route::post('user','App\Http\Controllers\UserController@getAuthenticatedUser');
});
NOTA: Las rutas que guardemos en api, tendrán por defecto la ruta /api
Ya tenemos todo listo para poder registrar usuarios y hacer login.
<h1>Enviando peticiones a nuestro backend</h1>Podemos usar Postman para realizar una petición en formato JSON con POST hacia la ruta /api/register:
{
"name" : "randomusername",
"password" : "strongkey123",
"password_confirmation" : "strongkey123",
"email" : "[email protected]"
}
Se puede ver como se registró correctamente nuestro usuario.
El inicio de sesión consiste en enviar las credenciales de acceso y obtener un token, que nos permitirá acceder a rutas que se necesita autenticación. La ruta de login es /api/login usando el método GET
{
"email" : "[email protected]",
"password" : "strongkey123"
}
Como último paso es acceder a una ruta protegida con nuestro token de autenticación.
Nuestro token se debe enviar con el header Authorization y colcando la palabra Bearer antes de nuestro token
Authorization: Bearer <nuestroToken>
La ruta para obtener los datos de usuario es /api/user mediante el método POST
Ahora sí, está todo listo.
Ya estás listo para crear tu backend en Laravel 8 para comunicarte con cualquier aplicación que quieras desarrollar.
Te invito a escribir en la caja de comentarios y, NUNCA PARES DE APRENDER
excelente. me pase todo el dia buscando esto . no sabia como hacerlo de manera eficiente en el back y quería algo que no fuera tan engorroso. tu tutorial me salvo la vida.
muchas gracias
una ves tiendo el token de acceso como puedo acceder a mis rutas protegidas en produccion osea como mando o como se deberia de hacer para que el token me reconosca ?
me encanto
Muy buen tutorial justo lo que buscaba solo una sugerencia en la parte donde mencionas php artisan jwt:secret para mi que soy nuevo en laravel pense que era como una prueba sin embargo revisando la documentacion se refiere a la secret key necesaria para realizar la encriptación creo que valdria la pena especificarlo.
Excelente tutorial, muchas gracias, en la definición de la ruta de login se usó el método post, pero después se hace la solicitud a esa ruta con el método get, así que normalmente ¿cuál de los dos métodos se usa para un login?
Está genial! gran aporte y supe fácil de implementar,
Una duda, alguna idea de como podría implementar 2 backends (diferentes frameworks) con jwt token? con que la autentificación la ejecuta laravel, no acabo de como puedo aplicarlo para esto
Excelente el tutorial, justo lo que estaba buscando, pero me está dando un error en la recuperación de los datos de user…
“status”: “Authorization Token not found”
Lo seguí hasta
Tymon\JWTAuth\Exceptions\JWTException: The token could not be parsed from the request in file E:\internet\www\pedidosresto\back-resto\vendor\tymon\jwt-auth\src\JWT.php on line 185
Alguna pista ???
Gracias!!
Tengo el mismo problema, en el archivo que esta en la ruta
app\http\Middleware\JwtMiddleware.php
<code><?phpnamespaceApp\Http\Middleware; useClosure; useIlluminate\Http\Request; useJWTAuth; useException; useTymon\JWTAuth\Http\Middleware\BaseMiddleware; classJwtMiddlewareextendsBaseMiddleware{ /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */publicfunctionhandle(Request $request, Closure $next){ try { $user = JWTAuth::parseToken()->authenticate(); } catch (Exception $e) { if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenInvalidException){ return response()->json(['status' => 'Token is Invalid']); }elseif ($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException){ return response()->json(['status' => 'Token is Expired']); }else{ return response()->json(['status' => 'Authorization Token not found', 'detail' => $e->getMessage(), 'error'=> $e]); } } return $next($request); } }
Asi te debe devolver el problema que tienes, por ejemplo yo en mi tabla de usuarios tengo el problema que no tengo un campo con el nombre id
<code> { "status": "Authorization Token not found", "detail": "SQLSTATE[42S22]: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]El nombre de columna 'id' no es válido. (SQL: select top 1 * from [std_Usuarios] where [id] is null)", "error": { "errorInfo": [ "42S22", 207, "[Microsoft][ODBC Driver 17 for SQL Server][SQL Server]El nombre de columna 'id' no es válido.", "42000", 8180, "[Microsoft][ODBC Driver 17 for SQL Server][SQL Server]No se puede preparar la instrucción o instrucciones." ] } }
Excelente aporte, gracias por compartir tu conocimiento, me fue de mucha ayuda, Bendiciones!!!