- Lab
- Core Tech

Guided: Developing a RESTful API with Authentication in Laravel
In this Guided Code Lab, you will learn how to utilize Laravel's built-in features to build your own RESTful API for managing resources. You will implement all of the CRUD operations with the resource controller and connect them to the API endpoints. Finally, you will also learn how to use Laravel Sanctum package to easily implement token-based authentication to restrict the usage of your API to registered users only.

Path Info
Table of Contents
-
Challenge
Introduction
In this Guided Code Lab, you will learn how to create a REST API in Laravel and how to protect it with authentication. Authentication will be implemented with the Laravel Sanctum package. The API will allow the users to manage items in some kind of a storage unit.
Each task can be validated individually by clicking on the Validate button next to it.
If you are stuck, you can always check out the details section of the task or the
solutions
directory. The task will give you feedback if you don't complete it correctly. A failed task will have one or more failed tests under the "checks" section of the task. You can check out the output of these failed tests to see what went wrong.The starting point of the Lab is a new Laravel application named "items-api". The current directory of the build-in Terminal will be set to the
items-api/
directory.Notice that you will have access to two Terminal windows.
- You can use the first Terminal to run the development server with the Artisan CLI or to run other Artisan commands. The Run button will automatically start the Artisan development server.
- The second Terminal can be used to test the API endpoints with the
curl
command. There will be an explanation of which commands you have to run as you get to each specific task.
-
Challenge
Creating the Item Resource
A REST API is a set of rules and conventions for building and interacting with web services. These types of APIs are often used to manage resources and in this lab you will manage the Item resource.
To do that, you first need to be able to store the instances of that resource in some kind of a database. To keep things simple, you can use SQLite. The database connection is already configured inside of the
.env
file with just one variable:DB_CONNECTION=sqlite
.The database file is already created inside of the default directory
database/database.sqlite
. If you need to create it in your own projects, it's enough to just create the file with the same name, which you can do with the touch command:touch database/database.sqlite
.After the database is configured, you need to create the Eloquent ORM model to manage the Item resource in the database. Once the migration is created, you need to specify the properties of the Item resource, which would correspond to columns in the database. You should also prepare the model for mass assignment. This will help you down the line, when you decide to create new items in the database. The migration file is now complete, but you need to migrate these changes so that the real items table can be created inside of the SQLite database.
-
Challenge
Implementing the Item's Controller and Routes
The
Item
model is ready. Now you need to implement some business logic that will actually let the user manage items through the API endpoints.The best way to implement CRUD (Create, Read, Update, Delete) operations on a single resource is to use Laravel's resource controllers. A resource controller will automatically create all of the actions you need for CRUD. When working with APIs, you don't need the
create
andedit
actions, since these are usually used for rendering HTML forms. The controller's actions are empty for now. However, even if you did add some logic already, you wouldn't be able to use it because each action needs to be connected to a specific route endpoint. This table shows which route needs to be connected to which action:| Verb | URI | Action | |-----------|-----------------------|---------| | GET |
/items
| index | | POST |/items
| store | | GET |/items/{item}
| show | | PUT/PATCH |/items/{item}
| update | | DELETE |/items/{item}
| destroy |Instead of specifically defining each route, you can utilize Laravel's special methods for creating resource routes, which will follow the rules of the table provided above.
The routes have to be created inside of the
app/routes/api.php
file. That file is specifically designed to work with API middleware, as opposed to theweb.php
file, which is used for monolithic applications. All routes placed inside of theapi.php
file will have the/api
prefix in the route path. -
Challenge
Creating and Showing Items
The controller is created and actions are connected to the appropriate resource routes. It's time to actually define the logic for each controller action.
The
store
action should receive thename
andstock
from the POST request and use that data to create a new Item in the database. If you want, you can now start up the server by clicking on the Run button or just runningphp artisan serve
in the first Terminal.After the server is running, you can use the second Terminal to try out the first action you created. To do that you can use this
curl
command:curl -X POST http://localhost:8000/api/items -H "Content-Type: application/json" -d '{"name": "Example Item", "stock": 10}'
About the
You can use the `curl` command to make requests to an API. The `-X` flag defines that the request will use the `POST` HTTP method because you need to send the `name` and `stock` data to the server. It is a good practice to use `-H` to define that you are sending data as JSON.curl
commandThe
-d
flag provides the actual data you want to send to the server. In this case, thePOST
request to the/api/items
route will trigger thestore
action in theItemController
.Of course, you can change the input data to whatever you want. This is not a task, but you should know how to try out your API endpoints. The successful response should return the same data you sent with the request.
If you want to check the items table directly from the database, you can use this command to see if you new item was saved:
sqlite3 database/database.sqlite "SELECT * FROM items;"
However, you will also be able to see all of the items from the database, once you define the actions for showing the resource. The
index
action usually returns all of the resource instances from the database. You can test this route with thiscurl
command:curl -X GET http://localhost:8000/api/items -H "Accept: application/json"
Finally, you should also implement the
show
action. This action should retrieve just one item, based on the route parameter from the route path. The parameter contains the id of the requested item. You can test this route with the followingcurl
command:curl -X GET http://localhost:8000/api/items/{id} -H "Accept: application/json"
Replace the
{id}
with the existing item id. If you created just one item, you can replace the id parameter with id1
. -
Challenge
Updating and Deleting Items
Users can now create and see items. In the spirit of RESTful APIs, you also need to implement the rest of CRUD operations.
Define the
update
action, which will be used to update the data of existing items in the database.Both fields from the request should use the
sometimes
validation rule because this will allow users to do a partial update, instead of always having to provide values for all of the fields. If you want, you can also test this endpoint withcurl
.Test the
You can use this command to test it: ``` curl -X PUT http://localhost:8000/api/items/1 -H "Content-Type: application/json" -d '{"name": "Updated Item Name", "stock": 20}' ```update
actionThis command will update the item with id
1
, but you can change that to some other id in the route parameter. The-d
flag will provide new data. You can also try to remove one of the fields because partial updates should also work.The
PUT
andPATCH
are often used interchangeably, althoughPUT
should be used for updating all of the fields, whilePATCH
should only do partial updates. In Laravel, you can use any of these two to access theupdate
route.To finish all of the CRUD operations, you still need to allow users to delete items. And that's it! You just finished defining all of the CRUD operations for the item resource. You have a functional REST API.
To test the
destroy
action, you can use thiscurl
command:curl -X DELETE http://localhost:8000/api/items/{id}
Of course, replace the
{id}
from the route parameter with the real id of the item that you want to remove. -
Challenge
Registering Users
The REST API for managing items is now finished. The next step is to implement authentication to protect the routes, so that only registered users can actually use the API.
Fortunately, Laravel has the Sanctum package for this very purpose. Before the version 10 of the Laravel framework, you had to install Sanctum yourself with the
composer
package manager and publish its configuration files to your project. However, since version 10, Sanctum is included by default in every new project you create.You can check out the
composer.json
file to see that the package is already an installed dependency. Also, thesanctum.php
configuration file is present inside of theconfig
directory, which means that Sanctum is already installed and configured.To utilize it, you first need to create some kind of an authentication controller. The
/register
route should allow guests to create an account for accessing your API. Registration will allow guests to become application users. Of course, you need to store the user information inside of the database.Fortunately, you can see that every new Laravel project already has few existing migrations. There is a migration for creating the users table and another for storing access tokens. Both of these are required by the Sanctum package. When you ran the migrations with the
php artisan migrate
command, Artisan also created all of these additional tables in the database.So you can use the existing
User
model to create new users. If you implemented everything correctly, you should be able to create new users with thecurl
command:curl -X POST http://localhost:8000/api/register -H "Content-Type: application/json" -d '{"name": "User1", "email": "user@example.com", "password": "pass", "password_confirmation": "pass"}'
Users also need to provide the password confirmation field because of the
confirmed
validation rule on thepassword
field.If you want to check the database table for users directly, you can use:
sqlite3 database/database.sqlite "SELECT * FROM users;"
-
Challenge
Implementing Login Functionality
Guests are now able to create user accounts for your application. You need to provide them with the
/login
route which they can use to authenticate. If they provide the correct credentials, Sanctum should send them an access token with the response. The defaultUser
model already has thehasApiTokens
trait included in the model's class. This is all you need to utilize Sanctum's methods onUser
instances.The
login
action should validate theemail
andpassword
from the request data. If both of these fields are valid, you can find the user in the database and return their access token. This implementation of thelogin
action will work, but only if the user definitely exists in the database. Also you are not checking if the password matches the user's password. These things need to be fixed. You can try to login with the existing account you created in the registration step. Of course, if you didn't create the account yet, go and create it with the/register
route. Once you do that you can usecurl
to provide the credentials to the/login
route:curl -X POST http://localhost:8000/api/login -H "Content-Type: application/json" -d '{"email": "user@example.com", "password": "pass"}'
If you provide the correct credentials, you will get an access token back from the server.
-
Challenge
Protecting the Routes with Authentication
Only registered users should be able to manage items in your application. To protect the API resources, you can use the Sanctum's middleware in the
api.php
file.This is how you could apply the middleware to a single route or a collection of resource routes:
Route::middleware('auth:sanctum')->apiResource('items', ItemController::class);
However, in most applications with authentication, you will put more than one route or resource under the protection of the authentication middleware. You can check if the routes are protected by using this command:
curl -X GET http://localhost:8000/api/items -H "Accept: application/json"
This command will simply try to access the route that shows all of the items. However, the response you should get is the
Unauthenticated
message.To access this route, you also need to provide the access token inside of the
Authorization
header. The value of this header isBearer
followed by the access token.curl -X GET http://127.0.0.1:8000/api/items -H "Accept: application/json" -H "Authorization: Bearer ACCESS_TOKEN"
Of course, you need to replace the
ACCESS_TOKEN
with the actual token you get back once you login. Try to login again and provide the access token in this header.Finally, it's also a good practice to create the
logout
action which will delete the existing access token. If you want to test this route, you can use this command with the existing access token:curl -X POST http://localhost:8000/api/logout -H "Accept: application/json" -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
And that's it! Congratulations, you just created a RESTful API with authentication in Laravel!
What's next? What more can you do to improve upon this basic API?
Here are some suggestions:
- Implement pagination for the
index
action, your server will be blocked with requests if it has to return all of the items from the database. - Use TLS certificate to set up the secure HTTPS connection. This is a must for all modern web applications with authentication, otherwise you risk vulnerabilities like the man-in-the-middle attack.
- To setup specific rules on what each user can do, you can simply add Sanctum abilities to the middleware.
- Implement rate limiting to protect your API from abuse. Laravel has built-in features for that.
- Version your API. The easiest way to do that is to place the version number directly inside of the route path.
- Use tools like Swagger to create a documentation for your API endpoints.
- Use tools like Laravel Telescope for debugging and monitoring your API's performance in production.
- Be mindful of Eloquent's performance. Use eager loading to reduce the number of queries to the database.
- Implement caching to store responses and reduce database queries for frequently accessed data.
- Implement pagination for the
What's a lab?
Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.
Provided environment for hands-on practice
We will provide the credentials and environment necessary for you to practice right within your browser.
Guided walkthrough
Follow along with the author’s guided walkthrough and build something new in your provided environment!
Did you know?
On average, you retain 75% more of your learning if you get time for practice.