Authentication is a fundamental aspect of building any web application, as it ensures that only authorized users can access sensitive data and perform actions within the application. Laravel, one of the most popular PHP web frameworks, offers several built-in authentication mechanisms. In the modern era of web development, token-based authentication has become increasingly popular as it is more secure and scalable than traditional cookie-based authentication. Laravel Sanctum is a package that provides a simple and secure way to implement token-based authentication in Laravel applications.
In this article, we will explore the Laravel Sanctum package and how it can be used to implement a simple token-based authentication system. We will cover the steps required to set up Laravel Sanctum, create the API endpoints for authentication, and issue and revoke user tokens. By the end of this article, we will have implemented a token-based authentication system that can be used in APIs and SPAs(Single Page Applications).
Prerequisites
To follow along with this article, we’ll need:
- Basic knowledge of PHP and Laravel.
- Understanding of HTTP clients like Postman.
Getting Started
Let’s start by creating a new project. We can do that by running the command below.
laravel new laravel_sanctum_app
Alternatively, we can run this command instead.
composer create-project laravel/laravel laravel_sanctum_app
Both commands will do the same and create a new Laravel project laravel_sanctum_app
in the specified directory.
Next, start our server to check if our project is running correctly.
For Windows users, execute the following command in the terminal:
cd laravel_sanctum_app
php artisan serve
For Mac users, use this instead:
cd laravel_sanctum_app
valet park
Laravel Valet is a development environment for macOS that always configures Mac to run Nginx in the background. For a comprehensive guide on setting up Laravel Valet, click here.
If everything works correctly, the output below will be displayed.
Installation and Setup
Laravel Sanctum now comes pre-installed with Laravel since version 7, whereas in earlier versions, it had to be installed separately.
Next, we’ll need to set up our database, and for the sake of this tutorial, we’ll use the SQLite database. We can do that by navigating to the .env file in the project's root directory.
DB_CONNECTION=sqlite
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=
Remove the crossed lines and make changes to the first line.
Next, we run our database migration.
php artisan migrate
Note: when this command run, a table called personal_access_tokens
is created in the database. This table stores the token for each user.
Building the API
The API will consist of 3 endpoints. The first endpoint, "register", will create a new user. The second endpoint, "login", will allow users to log in, and the last endpoint, "logout", will allow users to log out of the system.
First, we need to create the controller that will house these endpoints. We can do that by running the following command.
php artisan make:controller AuthController
This command will create a file named AuthController in the App\Http\Controllers directory.
Now open the routes/api.php file to create the routes that will be used in our application.
use App\Http\Controllers\AuthController;
Route::post('/register', [AuthController::class, 'register']);
Route::login('/login', [AuthController::class, 'login']);
Route::logout('/logout', [AuthController::class, 'logout']);
Open the AuthController and paste the following code snippet.
public function register(Request $request)
{
$validatedData = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8',
]);
$user = User::create([
'name' => $validatedData['name'],
'email' => $validatedData['email'],
'password' => Hash::make($validatedData['password']),
]);
return response()->json([
'name' => $user->name,
'email' => $user->email,
]);
}
In the code snippet above, we validate the request to ensure that all required variables are present and are of the required type. Then we persist the data into our user table by calling the Eloquent create method on an instance of our database. Then finally, a JSON response that shows the name and email is returned. We’re not creating a token here; the token will be created at the login point.
Now implement the login functionality.
public function login(Request $request){
$user = User::where('email', $request->email)->first();
if (! $user || ! Hash::check($request->password, $user->password))
{
return response()->json([
'message' => ['Username or password incorrect'],
]);
}
$user->tokens()->delete();
return response()->json([
'status' => 'success',
'message' => 'User logged in successfully',
'name' => $user->name,
'token' => $user->createToken('auth_token')->plainTextToken,
]);
}
Here we’re checking if the supplied email matches the user’s email in the database. An error is thrown if there’s no match or a different password is entered. Then because we do not want to create a new token for a user while the old token is still in the database, the old token is deleted, and a JSON response containing the new token is returned to the user.
Now finally, let’s create the endpoint responsible for logging out users.
public function logout(Request $request){
$request->user()->currentAccessToken()->delete();
return response()->json(
[
'status' => 'success',
'message' => 'User logged out successfully'
]);
}
The above code snippet deletes the token for the currently authenticated user and logs out the user.
Let's make a slight change to the routes/api.php file.
Route::post('/register', [AuthController::class, 'register']);
Route::login('/login', [AuthController::class, 'login']);
//new
Route::logout('/logout', [AuthController::class, 'logout'])->middleware('auth:sanctum');
We use Sanctum middleware to ensure that only authenticated users can access the logout endpoint. This means the user needs to be logged in and have a valid token before logging out.
Testing the API
To test our API, we can utilize any HTTP client that we prefer. However, in this article, Postman will be used to demonstrate the process.
Register a new user
To register a new user, a POST request should be made to the '/api/register' endpoint with the parameters "name," "email," and "password."
When running the server locally with the php artisan serve command, the URL to send the request to would be http://127.0.0.1:8000/api/register. In the case of Laravel Valet with the valet park command, the URL would be http://laravel_sanctum_app.test/api/register.
Login the user
To log a user in, send a POST request to the ‘/api/login’ endpoint with the parameters email and password.
Logout
To log out the user, copy the token from the login response and paste it into the "Bearer token" field located in the Authorization tab.
Conclusion
In conclusion, Laravel Sanctum provides a simple and secure solution for implementing token-based authentication in Laravel 9. With this package, we can easily generate and manage API tokens, authenticate and authorize users to access our API endpoints, and protect API routes using middleware.
This article shows how to set up Sanctum in a Laravel 9 application, generate and use API tokens for authentication, and protect API routes using middleware. Following the steps outlined in this article, we can easily implement token-based authentication in our Laravel 9 application using Laravel Sanctum.
Resources
For further reading, here are some resources worth checking out:
- Laravel Sanctum official documentation: https://laravel.com/docs/9.x/sanctum
- Laravel Sanctum tutorial by FreeCodeCamp: https://www.freecodecamp.org/news/how-to-use-sanctum-for-api-authentication-in-laravel/
Top comments (1)
I am a Laravel beginner and your article is usefull for me. Can you tell me how to use the api token from a web form.
Let see, there is a login form and when user fills corect username and password a token will be created. Then, because of that the user is authorize, and while be direct to certain web page.
So, how can I do that?.
Sorry for my bad English.
Thanks
Some comments have been hidden by the post's author - find out more