Skip to content

Commit 9ca10c2

Browse files
author
Gareth Redfern
authored
Update README.md
1 parent 097a9af commit 9ca10c2

File tree

1 file changed

+2
-234
lines changed

1 file changed

+2
-234
lines changed

README.md

Lines changed: 2 additions & 234 deletions
Original file line numberDiff line numberDiff line change
@@ -1,237 +1,5 @@
11
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400"></a></p>
22

3-
## Authentication Using Laravel Sanctum & Fortify for an SPA
4-
5-
Previously I wrote about using Laravel Sanctum to build an API for a Vue SPA to consume. [The article](/articles/vuejs-auth-using-laravel-sanctum), was a very basic intro using API tokens and local storage to maintain authentication state. While there’s nothing wrong with that method for testing out an idea, the preferred and more secure method is to use cookies and sessions. In this article we will dive into using Sanctum with Fortify in a Laravel API, consumed by a separate Vue SPA.
6-
7-
The project files for this article can be found on Github:
8-
9-
- [Larvel API](https://github.com/garethredfern/laravel-api)
10-
- [VueJS SPA](https://github.com/garethredfern/laravel-vue)
11-
12-
### Laravel & Package Install
13-
14-
First, set up the Laravel API as you normally would. My preferred option is to use Laravel [Sail](https://laravel.com/docs/8.x/sail), which I have written about [here](/articles/switching-to-laravel-sail). If you choose to run Laravel via Sail, your API will be accessible via http://localhost.
15-
16-
Next install [Sanctum](https://laravel.com/docs/8.x/sanctum#installation) & [Fortify](https://laravel.com/docs/8.x/fortify).
17-
18-
```bash
19-
sail composer require laravel/sanctum
20-
21-
sail artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
22-
```
23-
24-
```bash
25-
sail composer require laravel/fortify
26-
27-
sail artisan vendor:publish --provider="Laravel\Fortify\FortifyServiceProvider"
28-
```
29-
30-
> Note: I am using the sail command to enable artisan commands to run within the Docker container.
31-
32-
Next add Sanctum's middleware to your api middleware group within your application's app/Http/Kernel.php file:
33-
34-
```php
35-
'api' => [
36-
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
37-
'throttle:api',
38-
\Illuminate\Routing\Middleware\SubstituteBindings::class,
39-
],
40-
```
41-
42-
Ensure the FortifyServiceProvider class is registered within the providers array of your application's config/app.php file.
43-
44-
```php
45-
/*
46-
* Application Service Providers...
47-
*/
48-
49-
App\Providers\FortifyServiceProvider::class,
50-
```
51-
52-
Set up a seed for adding a test user, in the DatabaseSeeder.php file add the following:
53-
54-
```php
55-
\App\Models\User::factory(1)->create(
56-
[
57-
'name' => 'Luke Skywalker',
58-
'email' => '[email protected]',
59-
'email_verified_at' => null,
60-
]
61-
);
62-
```
63-
64-
Run the migrations. If you get an error using Sail, checkout my notes [here](/articles/switching-to-laravel-sail#a-couple-of-gotchas):
65-
66-
```bash
67-
sail artisan migrate --seed
68-
```
69-
70-
Don’t forget to add a sender address in the `.env` so that an email can be sent.
71-
72-
```bash
73-
74-
```
75-
76-
### Setting Up Sanctum
77-
78-
Sanctum needs some specific set up to enable it to work with a separate SPA. First lets add the following in your .env file:
79-
80-
```bash
81-
SANCTUM_STATEFUL_DOMAINS=localhost:8080
82-
SPA_URL=http://localhost:8080
83-
SESSION_DOMAIN=localhost
84-
```
85-
86-
The stateful domain tells Sanctum which domain you are using for the SPA. You can find the full notes and config for this in the config/sanctum.php file. As we are using cookies and sessions for authentication you need to add a session domain. This determines which domain the cookie is available to in your application. Full notes can be found in the config/session.php file and the [official documentation](https://laravel.com/docs/8.x/sanctum#spa-authentication).
87-
88-
Add the following to `app/Http/Kernel`
89-
90-
```php
91-
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
92-
93-
'api' => [
94-
EnsureFrontendRequestsAreStateful::class,
95-
'throttle:api',
96-
\Illuminate\Routing\Middleware\SubstituteBindings::class,
97-
],
98-
```
99-
100-
### Setting Up CORS
101-
102-
If you don’t get CORS set up correctly, it can be the cause (pardon the pun) of great frustration. The first thing to remember is that your SPA and API need to be running on the same top-level domain. However, they may be placed on different subdomains. Running locally (using Sail) the API will run on http://localhost and the SPA using the Vue CLI will normally run on http://localhost:8080 (the port may vary but that is OK).
103-
104-
With this in place we just need to add the routes which will be allowed via CORS. Most of the API endpoints will be via `api/*` but Fortify has a number of endpoints you need to add along with the fetching of `'sanctum/csrf-cookie'` add the following in your config/cors.php file:
105-
106-
```php
107-
'paths' => [
108-
'api/*',
109-
'login',
110-
'logout',
111-
'register',
112-
'user/password',
113-
'forgot-password',
114-
'reset-password',
115-
'sanctum/csrf-cookie',
116-
'email/verification-notification',
117-
],
118-
```
119-
120-
While you are in the config/cors.php file set the following:
121-
122-
```php
123-
'supports_credentials' => true,
124-
```
125-
126-
The above ensures you have the `Access-Control-Allow-Credentials` header with a value of `True` set. You can read more about this in the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials). We will be passing this header via the SPA but more on that when we move to set it up.
127-
128-
### Setting Up Fortify
129-
130-
Fortify also has a config file (config/fortify.php) which will need some changes. First set the `home` variable to point at the SPA URL, this can be done via the .env variable. This is where the API redirects to during authentication or password reset when the operations are successful and the user is authenticated.
131-
132-
```php
133-
'home' => env('SPA_URL') . '/dashboard',
134-
```
135-
136-
Next switch off using any Laravel views for the authentication features, the SPA is handling all of this.
137-
138-
```php
139-
'views' => false,
140-
```
141-
142-
Finally, turn on the authentication features you would like to use:
143-
144-
```php
145-
'features' => [
146-
Features::registration(),
147-
Features::resetPasswords(),
148-
Features::emailVerification(),
149-
Features::updateProfileInformation(),
150-
Features::updatePasswords(),
151-
],
152-
```
153-
154-
### Redirecting If Authenticated
155-
156-
Laravel provides a `RedirectIfAuthenticated` middleware which out of the box will try and redirect you to the home view if you are already authenticated. For the SPA to work you can add the following which will simply send back a 200 success message in a JSON response. We will then handle redirecting to the home page of the SPA using VueJS routing.
157-
158-
```php
159-
foreach ($guards as $guard) {
160-
if (Auth::guard($guard)->check()) {
161-
if ($request->expectsJson()) {
162-
return response()->json(['error' => 'Already authenticated.'], 200);
163-
}
164-
return redirect(RouteServiceProvider::HOME);
165-
}
166-
}
167-
```
168-
169-
### Email Verification
170-
171-
Laravel can handle email verification as it normally would but with one small adjustment to the `Authenticate` middleware. First. Let’s make sure your `App\Models\User` implements the `MustVerifyEmail` contract:
172-
173-
```php
174-
class User extends Authenticatable implements MustVerifyEmail
175-
{
176-
use Notifiable;
177-
178-
// ...
179-
}
180-
```
181-
182-
In the `Authenticate` Middleware change the `redirectTo` method to redirect to the SPA URL rather than a Laravel view:
183-
184-
```php
185-
protected function redirectTo($request)
186-
{
187-
if (! $request->expectsJson()) {
188-
return url(env('SPA_URL') . '/login');
189-
}
190-
}
191-
```
192-
193-
With this is in place Laravel will now send out the verification email and when a user clicks on the verification link it will do the necessary security checks and redirect back to your SPA’s URL.
194-
195-
### Reset Password
196-
197-
Setting up the reset password functionality in the API is as simple as following the [official docs](https://laravel.com/docs/8.x/passwords#reset-link-customization). For reference here is what you need to do.
198-
199-
Add the following at the top of `App\Providers\AuthServiceProvider`
200-
201-
```php
202-
use Illuminate\Auth\Notifications\ResetPassword;
203-
```
204-
205-
Add the following in the `AuthServiceProvider` boot method, this will create the URL which is used in the SPA with a generated token:
206-
207-
```php
208-
ResetPassword::createUrlUsing(function ($user, string $token) {
209-
return env('SPA_URL') . '/reset-password?token=' . $token;
210-
});
211-
```
212-
213-
To make this all work we will need to have a reset-password view in the SPA which handles the token and passes back the users new password. This will be explained fully in the creating of the SPA post which will follow, you can review the code on [Github](https://github.com/garethredfern/laravel-vue/blob/main/src/views/ResetPassword.vue).
214-
215-
### API Routes
216-
217-
Once you have all the authentication in place, any protected routes will need to use the `auth:sanctum` middleware guard. This will ensure that the user has been authenticated before they can view the requested data from the API. Here is a simple example of what those endpoints would look like.
218-
219-
```php
220-
use Illuminate\Http\Request;
221-
222-
Route::middleware('auth:sanctum')->get('/users/{user}', function (Request $request) {
223-
return $request->user();
224-
});
225-
```
226-
227-
### Conclusion
228-
229-
If you are wanting/needing to go down the route of having a completely separate SPA that consumes a Laravel API then hopefully this post has given you all the reference you need to get things set up for the API. In the next article we will focus on setting up the SPA.
230-
231-
If you would like to hear an excellent explanation from Taylor on the how these packages came about I highly recommend listening to his [podcast episode](https://blog.laravel.com/laravel-snippet-25-ecosystem-discussion-auth-recap-passport-sanctum).
232-
233-
The project files for this article can be found on Github:
234-
235-
- [Larvel API](https://github.com/garethredfern/laravel-api)
236-
- [VueJS SPA](https://github.com/garethredfern/laravel-vue)
3+
## Documentation
2374

5+
The full documentation for this demo app can be found at [Build a Laravel Vue Spa](https://laravelvuespa.com/).

0 commit comments

Comments
 (0)