Laravel is one of the most popular PHP application frameworks in the marketplace today. While it includes a simple authentication model, most large-scale applications will outgrow it pretty quickly. FusionAuth pairs well with Laravel because it can handle more complex user authentication models, roles, single sign-on, and more.
In this tutorial, we’ll set up a new Laravel application that uses FusionAuth to register and login users. All the code used here is available on GitHub. This application will show just a tiny sample of what you can do with FusionAuth, so be sure to check out the PHP Client Library and documentation for much more.
What we’ll cover
- Installing and setting up a local FusionAuth instance
- Setting up a new Laravel Application
- Installing and configuring the FusionAuth PHP package
- Registering a new user
- Logging a user in
- Showing the current user’s profile
- Logging out
- Conclusion and next steps
What you’ll need
- FusionAuth
- PHP (7+ preferred)
- Composer package manager
- PHP development environment
- Web browser
Please note this example application was tested using:
- PHP 7.2
- Laravel 7.30.4
Installing and setting up FusionAuth
Before we write any PHP code, FusionAuth must be downloaded and running on your local machine or server. FusionAuth is available for all major operating systems or it can be run in Docker.
Once you have FusionAuth running, you should log into the admin panel and create a new API Key and Application. This process is outlined here, but you can skip the OAuth settings for this tutorial.
Setting up a new Laravel Application
Assuming you have PHP and Composer installed on your machine, you can create a new Laravel application with the following command:
composer create-project --prefer-dist laravel/laravel fusionauth-laravel
There are several other options for installing and configuring Laravel, so be sure to check out the documentation. Once you’ve installed Laravel, you can use Homestead, Valet, Docker, or PHP’s built-in webserver to run it locally.
php artisan serve
Installing and configuring the FusionAuth PHP package
After you create the new Laravel application, you can use Composer to install the FusionAuth PHP Client. This will allow you to connect to the FusionAuth instance:
composer require fusionauth/fusionauth-client
To access your FusionAuth instance without putting sensitive information into version control, you should use Laravel’s environment file. Open your application’s .env
file and add your FusionAuth Application ID, API Key, and URL:
FUSIONAUTH_APP_ID=...
FUSIONAUTH_API_KEY=...
FUSIONAUTH_BASE_URL=http://localhost:9011
Finally, you can take advantage of Laravel’s dependency injection system by registering the FusionAuthClient
in the boot()
method of your app/Providers/AppServiceProvider.php
file:
//...
use FusionAuth\FusionAuthClient;
//...
class AppServiceProvider extends ServiceProvider
{
//...
public function boot()
{
$this->app->bind(FusionAuthClient::class, function ($app) {
return new FusionAuthClient(env('FUSIONAUTH_API_KEY'), env('FUSIONAUTH_BASE_URL'));
});
}
//...
}
Including the FusionAuthClient
in Laravel’s service provider will allow you to access it from any class in your application by passing it to the __construct
method.
At this point, your Laravel application is ready to connect to your FusionAuth instance. Next, you will create the Views and Controllers that will handle the display and business logic.
Registering a new user
We are going to create a form and layout to register users. You will need to create a view file to display the registration form. Create a new view called register.blade.php
in the resources/views/
directory of your Laravel app:
@extends('layout')
@section('content')
<h1>Register</h1>
<p>Create an account in our demo app.</p>
<form class="pure-form pure-form-stacked" action="/register" method="post">
@csrf
<label for="email">Email Address</label>
<input type="email" name="email" required>
<label for="password">Password</label>
<input type="password" minlength="8" name="password" required>
<input class="pure-button pure-button-primary" type="submit" value="Register">
</form>
<p>Already have an account? <a href="/">Login here</a></p>
@endsection
You’ll notice that this file requires a Layout file as well. Create a new file called layout.blade.php
in the same folder and add the following:
<html>
<head>
<title>FusionAuth Laravel Demo</title>
<link rel="stylesheet" href="https://unpkg.com/purecss@2.0.1/build/pure-min.css">
</head>
<body>
<div class="pure-g" style="justify-content: center;">
<div class="pure-u-1-3">
@yield('content')
</div>
</div>
</body>
</html>
This layout file brings in a stylesheet that includes Pure CSS - a minimal web styling library - and a container for our app’s primary content. These styles are purely cosmetic, so feel free to use your own stylesheets instead.
Next, create a new register user controller using the Artisan command line tool:
php artisan make:controller RegisterUser --invokable
php artisan make:controller <controller_name> --invokable
BEFORE creating the corresponding route in web.php
(see additional info below) In this single action controller, you should:
- Import the FusionAuth PHP Client
- Send the email and password input to the FusionAuth API via the PHP Client
- Handle any errors
- Redirect users to the home page (where they can log in) if registration is successful
Open up the app/Http/Controllers/RegisterUser.php
file created by the Artisan
command above and add the following:
//..
use FusionAuth\FusionAuthClient;
//..
//..
class RegisterUser extends Controller
{
private $authClient;
public function __construct(FusionAuthClient $authClient)
{
$this->authClient = $authClient;
}
public function __invoke(Request $request)
{
$clientRequest = [
'registration' => ['applicationId' => env('FUSIONAUTH_APP_ID')],
'sendSetPasswordEmail' => false,
'user' => [
'password' => $request->get('password'),
'email' => $request->get('email'),
'passwordChangeRequired' => false,
'twoFactorEnabled' => false,
],
];
$clientResponse = $this->authClient->register(null, $clientRequest);
if (!$clientResponse->wasSuccessful()) {
return redirect()->back();
}
return redirect('/');
}
}
//..
Finally, you’ll need to create two routes to register new users: one to display the registration form and another to process the data and interact with the FusionAuth client. Add the following lines to your routes/web.php
file (remove the welcome route):
Route::view('/register', 'register');
Route::post('/register', 'RegisterUser');
At this point, you should be able to access the /register
route in your Laravel application and successfully register a new user in FusionAuth.
use FusionAuth\FusionAuthClient;
Let’s take a look at our progress
Before we built out and called the registration functionality above, no new users had been added or registered.
Behold our newly registered user! Take a moment to reflect on your newfound powers and coding prowess!
Our user even has a cool default avatar!
Logging a user in
Now that users can register a new account, you’ll need to allow them to login using the email and password they created during registration.
The login form is very similar to the registration form created in the previous step, but it will submit entries to the /login
route instead of /register
. Create a new file at resources/views/login.blade.php
and add the HTML below:
@extends('layout')
@section('content')
<h1>Login</h1>
<p>Enter your username and password to login.</p>
<form class="pure-form pure-form-stacked" action="/login" method="post">
@csrf
<label for="email">Email Address</label>
<input type="email" name="email" required>
<label for="password">Password</label>
<input type="password" minlength="8" name="password" required>
<input class="pure-button pure-button-primary" type="submit" value="Login">
</form>
<p>Don't have an account yet? <a href="/register">Register here</a></p>
@endsection
To process user logins, you’ll need to create another single action controller. First, run the Artisan
command:
php artisan make:controller LoginUser --invokable
This time, your controller will use the login()
method of the FusionAuth PHP Client to validate the user’s login credentials and get their user data from the database. The LoginUser
controller will also save the user data to a session variable. This allows you to maintain the user’s profile data in your application’s state without accessing the FusionAuth API on every page load.
Open the app/Http/Controllers/LoginUser.php
file and add the following:
//..
use FusionAuth\FusionAuthClient;
//..
//..
class LoginUser extends Controller
{
private $authClient;
public function __construct(FusionAuthClient $authClient)
{
$this->authClient = $authClient;
}
public function __invoke(Request $request)
{
$clientRequest = [
'applicationId' => env('FUSIONAUTH_APP_ID'),
'ipAddress' => $request->ip(),
'loginId' => $request->get('email'),
'password' => $request->get('password'),
];
$clientResponse = $this->authClient->login($clientRequest);
if (!$clientResponse->wasSuccessful()) {
return redirect()->back();
}
session(['user' => (array) $clientResponse->successResponse->user]);
return redirect('profile');
}
}
//..
Finally, this will require two new routes, so open your routes/web.php
file again and add the following lines:
Route::view('/', 'login');
Route::post('/login', 'LoginUser');
The first route will display a new view file that includes an email and password input field. The second route will use a new action controller to log a user in via FusionAuth. Your login page should look like this:
Now when you log in using the new form, you’ll be redirected to /profile
, but that page doesn’t exist yet (hence, the 404 error).
Showing the current user’s profile
Users shouldn’t be able to access the /profile
route until they’ve logged in, and your application has stored their user data into session storage. Laravel uses the concept of Middleware to protect specific routes from unauthorized access.
Before you create the profile page, open up the app/Http/Middleware/Authenticate.php
file that came with Laravel. Since you’re using FusionAuth instead of the default Laravel user authentication, you can completely replace the file’s contents with the following:
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\AuthenticationException;
class Authenticate
{
public function handle($request, \Closure $next)
{
$user = session()->get('user');
if (!$user) {
throw new AuthenticationException('You must login to access this page.', [], '/');
}
return $next($request);
}
}
To use this middleware to prevent users who aren’t logged in from accessing the /profile
page, you can add it to the routes file. Open up the routes/web.php
file again and add the following line:
Route::view('/profile', 'profile')->middleware('auth');
Now you can create a profile.blade.php
file in your resources/views/
directory that shows the user’s FusionAuth ID and email address:
@extends('layout')
@section('content')
<h1>Profile</h1>
<p><strong>User ID: </strong> {{ session()->get('user')['id'] }}</p>
<p><strong>Email: </strong> {{ session()->get('user')['email'] }}</p>
<a href="/logout">Logout</a>
@endsection
Any other user data you choose to store in FusionAuth will be available in the session()->get('user')
array if you’d like to show it to logged-in users.
When you log in, you should see a profile page that looks something like this:
Logging out
Finally, you can create a controller and route that will flush a user’s session data and call the FusionAuthClient::logout()
method, logging them out of the application.
Use the following Artisan
command to create a new controller:
php artisan make:controller LogoutUser --invokable
Now open the app/Http/Controllers/LogoutUser.php
file and add the following:
//...
use FusionAuth\FusionAuthClient;
//...
class LogoutUser extends Controller
{
private $authClient;
public function __construct(FusionAuthClient $authClient)
{
$this->authClient = $authClient;
}
public function __invoke()
{
$this->authClient->logout(false);
session()->flush();
return redirect('/');
}
}
Finally, open up your routes/web.php
file and add a new logout
route:
Route::get('/logout', 'LogoutUser');
Now when a logged-in user viewing their profile clicks the Logout
link, Laravel will delete their session data and send them back to the home page to login.
Conclusion and next steps
I hope this minimal working example gives you a good starting point for integrating FusionAuth into your Laravel application. There are many other things you should consider if you’re building authentication into a production application. For example, I’ve added flash messages for errors and successes to the code repository on GitHub. You will probably also want to create other workflows like deleting users, updating emails and passwords, setting user roles and permissions, and forgot password workflows. All of these things are possible using FusionAuth and Laravel.
If you have questions or need help integrating your Laravel application with FusionAuth, feel free to leave a comment below.