Tutorial Laravel 8 API REST con autentificación JWT (CRUD)

Requisitos

Para seguir el tutorial utilizaremos una serie de herramientas que seguramente debas de tener instalado en tu equipo. Las herramientas son las siguientes:

  • Composer: para instalar los paquetes y dependencias.
  • Un editor de código: recomiendo Visual Studio Code.
  • Un entorno de desarrollo (opcional): personalmente utilizo Laragon, pero puedes utilizar cualquier otro o incluso el comando «php artisan serve».
  • Una base de datos MySQL/MariaDB: Si utilizas Laragon, Xamp, Wamp, etc ya te incluye la instalación de gestor de base de datos.
  • Un visualizador de base de datos: En mi caso utilizo Heidi, pero puedes utilizar el PHPMyAdmin si te sientes más cómodo con él.
  • Postman: Para probar nuestra API, si utilizas otro eres libre de usarlo.
  • Conocimientos básicos del funcionamiento de Laravel.

Instalación de Laravel

Para realizar las pruebas te recomiendo realizar una instalación limpia de Laravel 8, si ejecutas este procedimiento en una instalación que ya hayas instalado algún paquete es posible que tengas algun conflicto.

El primer paso es asegurarnos es descargar la última versión del instalador de Laravel, para ello ejecutamos el siguiente comando en un terminal:

composer global require laravel/installer
Lenguaje del código: PHP (php)
Instalación Laravel API REST JWT

Ahora crearemos el proyecto «apirest» sobre el que realizaremos las pruebas de la API REST. En la terminal navegamos al directorio donde queramos realizar la instalación de Laravel y ejecutamos el siguiente comando:

laravel new apirest
Lenguaje del código: JavaScript (javascript)
Instalación Laravel API REST JWT

Para acabar nos aseguramos que tengamos la versión de Laravel 8, navegamos al directorio «apirest» y ejecutamos el siguiente comando:

php artisan -V
Tutorial Laravel 8 API REST con autentificación JWT (CRUD) 1

Este tutorial se realiza sobre la versión 8 de Laravel que es la última el día que realizo el tutorial. Eso no significa que este tutorial de creación de una API REST no sea válido para una versión superior de Laravel, es posible que cambien algunos pasos.

Si os encontráis algún problema con una versión superior dejarlo en los comentarios e intento ayudaros.

Instalar Tymon JWTAuth

Para realizar la autentificación mediante JWT (JSON Web Tokens) utilizaremos el paquete Tymon JWTAuth, he probado varios y este es el que mejor resultado me ha dado. Básicamente seguiremos la documentación oficial, así que tenla presente.

Para realizar la instalación del paquete escribimos el siguiente comando (recuerda que debes ejecutarlo desde el directorio de Laravel):

composer require tymon/jwt-auth
Lenguaje del código: JavaScript (javascript)
Laravel 8 API REST JWT instalación JWT Auth

Después de haber instalado el paquete publicamos la configuración por si más adelante debemos realizar alguna modificación en la configuración. Para realizar esto ejecutamos el siguiente comando:

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
Lenguaje del código: JavaScript (javascript)
Laravel 8 API REST JWT instalación JWT Auth

Por último, generaremos la Key con la que se cifraran los tokens, esto lo hacemos mediante el siguiente comando:

php artisan jwt:secret
Lenguaje del código: CSS (css)
Laravel 8 API REST JWT instalación JWT Auth

Con esto ya hemos realizado todos los pasos de instalación del paquete. Recuerda que una vez que lleves este proyecto a producción tendrás que volver a generar la Key en el propio servidor de producción.

Configuración Tymon JWTAuth

No solo basta con la instalación del paquete, también debemos realizar una serie de modificaciones en nuestro Laravel 8 para que la autentificación de la API REST funcione correctamente.

Modificar User model

Debemos modificar el modelo de usuarios situado en «app/Models/User.php» y en la instancia de la clase la parte de «class User extends Authenticatable» debemos añadir al final implements JWTSubject quedando así «class User extends Authenticatable implements JWTSubject«.

Recuerda instanciar la clase que acabamos de implementar mediante «use Tymon\JWTAuth\Contracts\JWTSubject;«.

Dentro de la clase debajo de la parte que hemos modificado debemos cambiar «use HasApiTokens, HasFactory, Notifiable;» por «use HasFactory, Notifiable;». Para acabar eliminamos el «use Laravel\Sanctum\HasApiTokens;» ya no lo necesitamos.

Para acabar en esta clase debemos de crear estas dos funciones públicas:

public function getJWTIdentifier() { return $this->getKey(); } public function getJWTCustomClaims() { return []; }
Lenguaje del código: PHP (php)

Básicamente tu User.php debe de quedar tal que así:

<?php namespace App\Models; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Tymon\JWTAuth\Contracts\JWTSubject; class User extends Authenticatable implements JWTSubject { use HasFactory, Notifiable; /** * The attributes that are mass assignable. * * @var string[] */ protected $fillable = [ 'name', 'email', 'password', ]; /** * The attributes that should be hidden for serialization. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; /** * The attributes that should be cast. * * @var array */ protected $casts = [ 'email_verified_at' => 'datetime', ]; public function getJWTIdentifier() { return $this->getKey(); } public function getJWTCustomClaims() { return []; } }
Lenguaje del código: PHP (php)

Modificar auth config

En el fichero «config/auth.php» buscamos la parte en la que dice lo siguiente:

'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], ],
Lenguaje del código: PHP (php)

Y la modificamos quedando de la siguiente forma:

'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'jwt', 'provider' => 'users', ], ],
Lenguaje del código: PHP (php)

Creación de alias

Para acabar crearemos unos alias que nos facilitaran instancia las clases del paquete, para ello abrimos el archivo «config/app.php» y en la parte de aliases agregamos lo siguiente al final:

//Customs 'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class, 'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class,
Lenguaje del código: PHP (php)

Quedando así la parte de los alias:

'aliases' => [ 'App' => Illuminate\Support\Facades\App::class, 'Arr' => Illuminate\Support\Arr::class, 'Artisan' => Illuminate\Support\Facades\Artisan::class, 'Auth' => Illuminate\Support\Facades\Auth::class, 'Blade' => Illuminate\Support\Facades\Blade::class, 'Broadcast' => Illuminate\Support\Facades\Broadcast::class, 'Bus' => Illuminate\Support\Facades\Bus::class, 'Cache' => Illuminate\Support\Facades\Cache::class, 'Config' => Illuminate\Support\Facades\Config::class, 'Cookie' => Illuminate\Support\Facades\Cookie::class, 'Crypt' => Illuminate\Support\Facades\Crypt::class, 'Date' => Illuminate\Support\Facades\Date::class, 'DB' => Illuminate\Support\Facades\DB::class, 'Eloquent' => Illuminate\Database\Eloquent\Model::class, 'Event' => Illuminate\Support\Facades\Event::class, 'File' => Illuminate\Support\Facades\File::class, 'Gate' => Illuminate\Support\Facades\Gate::class, 'Hash' => Illuminate\Support\Facades\Hash::class, 'Http' => Illuminate\Support\Facades\Http::class, 'Lang' => Illuminate\Support\Facades\Lang::class, 'Log' => Illuminate\Support\Facades\Log::class, 'Mail' => Illuminate\Support\Facades\Mail::class, 'Notification' => Illuminate\Support\Facades\Notification::class, 'Password' => Illuminate\Support\Facades\Password::class, 'Queue' => Illuminate\Support\Facades\Queue::class, 'RateLimiter' => Illuminate\Support\Facades\RateLimiter::class, 'Redirect' => Illuminate\Support\Facades\Redirect::class, // 'Redis' => Illuminate\Support\Facades\Redis::class, 'Request' => Illuminate\Support\Facades\Request::class, 'Response' => Illuminate\Support\Facades\Response::class, 'Route' => Illuminate\Support\Facades\Route::class, 'Schema' => Illuminate\Support\Facades\Schema::class, 'Session' => Illuminate\Support\Facades\Session::class, 'Storage' => Illuminate\Support\Facades\Storage::class, 'Str' => Illuminate\Support\Str::class, 'URL' => Illuminate\Support\Facades\URL::class, 'Validator' => Illuminate\Support\Facades\Validator::class, 'View' => Illuminate\Support\Facades\View::class, //Customs 'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class, 'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class, ],
Lenguaje del código: PHP (php)

Configuración base de datos y migraciones

No quiero realizar una aplicación demasiado complicada de entender, ya que la función de este artículo es que sea algo simple que puedas poner en práctica rápidamente.

Básicamente, realizaremos una aplicación que utilizará las migraciones de usuario incluidas con Laravel y crearemos una tabla de artículos.

Configurando la base de datos en Laravel

Deberías tener ya creada una base de datos MySQL o MariaDb en tu entorno de desarrollo ahora simplemente vamos a configurarla en el fichero .env que encontrarás en el directorio raíz.

Simplemente debes modificar estos parámetros con los datos de acceso a tu base de datos:

DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=apirest DB_USERNAME=root DB_PASSWORD=

Creación de la tabla Products

Empezamos creando la migración con el siguiente comando:

php artisan make:migration create_products_table
Lenguaje del código: CSS (css)
Laravel 8 API REST JWT crear tablas bd

A continuación vamos a editar la migración que acabamos de crear, esta se encuentra en «database/migrations/nombremigracion.php». Modificamos todo el contenido de la migración por el siguiente:

<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateProductsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('products', function (Blueprint $table) { $table->id(); $table->string('name', 50); $table->string('description', 150); $table->decimal('stock'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('products'); } }
Lenguaje del código: PHP (php)

Después ejecutamos todas las migraciones mediante el siguiente comando:

php artisan migrate
Laravel 8 API REST JWT crear tablas bd

Si se ha ejecutado correctamente todo deberías tener una respuesta como la de la imagen, si revisas la base de datos con Heidi o PhpMyAdmin deberías de ver una tabla de users y la de products aparte de las que crea Laravel 8 para procesos internos.

Laravel 8 API REST JWT crear tablas bd

Para acabar creamos el modelo que utilizaremos para trabajar con Eloquent con la tabla que acabamos de crear. Para ello ejecutamos el siguiente comando:

php artisan make:model Product
Lenguaje del código: CSS (css)

Este comando nos creará un modelo en «App/Models/Product.php» lo modificamos por lo siguiente:

<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Product extends Model { use HasFactory; protected $fillable = [ 'name', 'description', 'stock', ]; }
Lenguaje del código: PHP (php)

Creación del AuthController

A continuación crearemos el controlador que realizará toda la gestión con Tymon JWT Auth para registrar usuarios, para iniciar sesión y para cerrar la sesión. Empezamos creando el controlador mediante el siguiente comando:

php artisan make:controller V1/AuthController

Nos creará un controlador en «app/Http/Controllers/V1/AuthController.php».

Seguramente te preguntas por qué he creado el controlador en el directorio V1 en vez de en la raíz de Controllers, esto es importante hacerlo porque cuando haces una API nunca sabes las dimensiones que puede tener o si en un futuro quieres hacer grandes cambios.

Si en un futuro decidieras cambiar una gran parte de tu API puedes crear los cambios en un directorio V2 y dejar la versión vieja como referencia.

Volviendo al tema del artículo procedamos a modificar el controlador que acabamos de crear con lo siguiente:

<?php namespace App\Http\Controllers\V1; use App\Http\Controllers\Controller; use JWTAuth; use App\Models\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Tymon\JWTAuth\Exceptions\JWTException; use Symfony\Component\HttpFoundation\Response; use Illuminate\Support\Facades\Validator; class AuthController extends Controller { //Función que utilizaremos para registrar al usuario public function register(Request $request) { //Indicamos que solo queremos recibir name, email y password de la request $data = $request->only('name', 'email', 'password'); //Realizamos las validaciones $validator = Validator::make($data, [ 'name' => 'required|string', 'email' => 'required|email|unique:users', 'password' => 'required|string|min:6|max:50', ]); //Devolvemos un error si fallan las validaciones if ($validator->fails()) { return response()->json(['error' => $validator->messages()], 400); } //Creamos el nuevo usuario $user = User::create([ 'name' => $request->name, 'email' => $request->email, 'password' => bcrypt($request->password) ]); //Nos guardamos el usuario y la contraseña para realizar la petición de token a JWTAuth $credentials = $request->only('email', 'password'); //Devolvemos la respuesta con el token del usuario return response()->json([ 'message' => 'User created', 'token' => JWTAuth::attempt($credentials), 'user' => $user ], Response::HTTP_OK); } //Funcion que utilizaremos para hacer login public function authenticate(Request $request) { //Indicamos que solo queremos recibir email y password de la request $credentials = $request->only('email', 'password'); //Validaciones $validator = Validator::make($credentials, [ 'email' => 'required|email', 'password' => 'required|string|min:6|max:50' ]); //Devolvemos un error de validación en caso de fallo en las verificaciones if ($validator->fails()) { return response()->json(['error' => $validator->messages()], 400); } //Intentamos hacer login try { if (!$token = JWTAuth::attempt($credentials)) { //Credenciales incorrectas. return response()->json([ 'message' => 'Login failed', ], 401); } } catch (JWTException $e) { //Error chungo return response()->json([ 'message' => 'Error', ], 500); } //Devolvemos el token return response()->json([ 'token' => $token, 'user' => Auth::user() ]); } //Función que utilizaremos para eliminar el token y desconectar al usuario public function logout(Request $request) { //Validamos que se nos envie el token $validator = Validator::make($request->only('token'), [ 'token' => 'required' ]); //Si falla la validación if ($validator->fails()) { return response()->json(['error' => $validator->messages()], 400); } try { //Si el token es valido eliminamos el token desconectando al usuario. JWTAuth::invalidate($request->token); return response()->json([ 'success' => true, 'message' => 'User disconnected' ]); } catch (JWTException $exception) { //Error chungo return response()->json([ 'success' => false, 'message' => 'Error' ], Response::HTTP_INTERNAL_SERVER_ERROR); } } //Función que utilizaremos para obtener los datos del usuario y validar si el token a expirado. public function getUser(Request $request) { //Validamos que la request tenga el token $this->validate($request, [ 'token' => 'required' ]); //Realizamos la autentificación $user = JWTAuth::authenticate($request->token); //Si no hay usuario es que el token no es valido o que ha expirado if(!$user) return response()->json([ 'message' => 'Invalid token / token expired', ], 401); //Devolvemos los datos del usuario si todo va bien. return response()->json(['user' => $user]); } }
Lenguaje del código: PHP (php)

Creación del ProductsController

Ahora crearemos nuestro CRUD de productos, concretamente haremos que se puedan listar productos y ver uno en concreto sin autentificación y para editarlo, crear uno nuevo o eliminarlo, se necesitará autentificación.

Creamos el controlador con el siguiente comando:

php artisan make:controller V1/ProductsController

Nos creará un controlador en «app/Controllers/V1/ProductsController.php» lo editamos con el siguiente código:

<?php namespace App\Http\Controllers\V1; use App\Http\Controllers\Controller; use App\Models\Product; use Illuminate\Http\Request; use JWTAuth; use Symfony\Component\HttpFoundation\Response; use Illuminate\Support\Facades\Validator; class ProductsController extends Controller { protected $user; public function __construct(Request $request) { $token = $request->header('Authorization'); if($token != '') //En caso de que requiera autentifiación la ruta obtenemos el usuario y lo almacenamos en una variable, nosotros no lo utilizaremos. $this->user = JWTAuth::parseToken()->authenticate(); } /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { //Listamos todos los productos return Product::get(); } /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { //Validamos los datos $data = $request->only('name', 'description', 'stock'); $validator = Validator::make($data, [ 'name' => 'required|max:50|string', 'description' => 'required|max:50|string', 'stock' => 'required|numeric', ]); //Si falla la validación if ($validator->fails()) { return response()->json(['error' => $validator->messages()], 400); } //Creamos el producto en la BD $product = Product::create([ 'name' => $request->name, 'description' => $request->description, 'stock' => $request->stock, ]); //Respuesta en caso de que todo vaya bien. return response()->json([ 'message' => 'Product created', 'data' => $product ], Response::HTTP_OK); } /** * Display the specified resource. * * @param \App\Models\Product $product * @return \Illuminate\Http\Response */ public function show($id) { //Bucamos el producto $product = Product::find($id); //Si el producto no existe devolvemos error no encontrado if (!$product) { return response()->json([ 'message' => 'Product not found.' ], 404); } //Si hay producto lo devolvemos return $product; } /** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param \App\Models\Product $product * @return \Illuminate\Http\Response */ public function update(Request $request, $id) { //Validación de datos $data = $request->only('name', 'description', 'stock'); $validator = Validator::make($data, [ 'name' => 'required|max:50|string', 'description' => 'required|max:50|string', 'stock' => 'required|numeric', ]); //Si falla la validación error. if ($validator->fails()) { return response()->json(['error' => $validator->messages()], 400); } //Buscamos el producto $product = Product::findOrfail($id); //Actualizamos el producto. $product->update([ 'name' => $request->name, 'description' => $request->description, 'stock' => $request->stock, ]); //Devolvemos los datos actualizados. return response()->json([ 'message' => 'Product updated successfully', 'data' => $product ], Response::HTTP_OK); } /** * Remove the specified resource from storage. * * @param \App\Models\Product $product * @return \Illuminate\Http\Response */ public function destroy($id) { //Buscamos el producto $product = Product::findOrfail($id); //Eliminamos el producto $product->delete(); //Devolvemos la respuesta return response()->json([ 'message' => 'Product deleted successfully' ], Response::HTTP_OK); } }
Lenguaje del código: PHP (php)

Creación del Middleware

A continuación crearemos un Middleware que se encargará de validar el token del usuario, para ello ejecutamos el siguiente comando:

php artisan make:middleware JwtMiddlware
Lenguaje del código: CSS (css)

Nos creará el fichero «app/Http/Middleware/JwtMiddleware.php» lo editamos y introducimos el siguiente código:

<?php namespace App\Http\Middleware; use Closure; use JWTAuth; use Exception; use Tymon\JWTAuth\Http\Middleware\BaseMiddleware; use Illuminate\Http\Request; class JwtMiddlware { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle(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'], 401); } else if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException) { return response()->json(['status' => 'Token is Expired'], 401); } else { return response()->json(['status' => 'Authorization Token not found'], 401); } } return $next($request); } }
Lenguaje del código: PHP (php)

A continuación añadimos los siguientes Middlewares en el fichero «app/Http/Kernel.php» en la parte protected routeMiddleware.

'jwt.verify' => \App\Http\Middleware\JwtMiddlware::class, 'jwt.auth' => 'Tymon\JWTAuth\Middleware\GetUserFromToken', 'jwt.refresh' => 'Tymon\JWTAuth\Middleware\RefreshToken',
Lenguaje del código: PHP (php)

Quedándonos así el código del $routeMiddleware:

protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, //Custom 'jwt.verify' => \App\Http\Middleware\JwtMiddlware::class, 'jwt.auth' => 'Tymon\JWTAuth\Middleware\GetUserFromToken', 'jwt.refresh' => 'Tymon\JWTAuth\Middleware\RefreshToken', ];
Lenguaje del código: PHP (php)

Configurar el fichero de rutas

Por último, ya solo nos queda configurar las rutas de la API REST, el fichero sobre el que trabajaremos es el «routes/api.php», sustituimos el contenido por el siguiente:

<?php use App\Http\Controllers\V1\ProductsController; use App\Http\Controllers\V1\AuthController; use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; /* |-------------------------------------------------------------------------- | API Routes |-------------------------------------------------------------------------- | | Here is where you can register API routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | is assigned the "api" middleware group. Enjoy building your API! | */ Route::prefix('v1')->group(function () { //Prefijo V1, todo lo que este dentro de este grupo se accedera escribiendo v1 en el navegador, es decir /api/v1/* Route::post('login', [AuthController::class, 'authenticate']); Route::post('register', [AuthController::class, 'register']); Route::get('products', [ProductsController::class, 'index']); Route::get('products/{id}', [ProductsController::class, 'show']); Route::group(['middleware' => ['jwt.verify']], function() { //Todo lo que este dentro de este grupo requiere verificación de usuario. Route::post('logout', [AuthController::class, 'logout']); Route::post('get-user', [AuthController::class, 'getUser']); Route::post('products', [ProductsController::class, 'store']); Route::put('products/{id}', [ProductsController::class, 'update']); Route::delete('products/{id}', [ProductsController::class, 'destroy']); }); });
Lenguaje del código: PHP (php)

Probando la API REST con Postman

Habiendo configurado las rutas nos quedará la siguiente estructura de nuestra API REST.

MétodoPathAutentificación
POSTapi/v1/loginNO
POSTapi/v1/registerNO
POST api/v1/logout
POSTapi/v1/get-user
GETapi/v1/productsNO
GETapi/v1/products/{id}NO
POST api/v1/products
PUTapi/v1/products/{id}
DELETEapi/v1/products/{id}

A continuación vamos a probar nuestra API REST mediante Postman, configura Postman como en las imágenes.

Ruta registro

Laravel 8 API REST

Aquí puedes apreciar que al realizar el registro nos devuelve el token, guárdalo que lo necesitaremos para cuando realicemos las peticiones que requieren autentificación.

Ruta Logout

Laravel 8 API REST

Con el token de la anterior ruta probamos el logout, esta ruta nos sirve para invalidar el token y que ya no se pueda autentificar con él.

Ruta login

Laravel 8 API REST

Ruta get user

Esta ruta la utilizaremos para verificar que el token del usuario no haya expirado (si estuviese expirado nos devolvería un error Unauthorized) y para obtener los datos de los usuarios. Escribe el token de la ruta login (recuerda que el de la ruta de registro lo hemos borrado).

Laravel 8 API REST

Creación de producto

El primer paso sería ir a la pestaña authorization, seleccionar Bearer token y escribir el token que validamos mediante get user.

Laravel 8 API REST

Creamos un producto de prueba.

Laravel 8 API REST

Actualizamos el producto

Laravel 8 API REST
Laravel 8 API REST

Mostramos todos los productos

Laravel 8 API REST

Mostrar un producto

Laravel 8 API REST

Eliminar un producto

Laravel 8 API REST
Laravel 8 API REST

Código fuente Laravel 8 API REST con autentificación

Puedes descargar el código fuente en este enlace.

Deja un comentario