Published: 2020-01-12

Filed under:

VueJS Auth Using Laravel Sanctum

Laravel Sanctum is a new package built by Taylor offering a simple authentication system for SPA's. Having just completed my first large SPA using VueJS and Laravel as the API I thought it would be good to dive into Sanctum and see how it works.

You can find the source code to the demos I set up here:

The first thing to do is set up your Laravel project as you normally would install Sanctum. Run the migrations and seed the database with the user seed so that you have a user to test auth against.

With Laravel set up there were two controllers needed to give us basic login and logout for the SPA:

The code in these two controllers basically follows the instructions provided in the Sanctum README and should be fairly self explanatory. The login controller checks the users credentials and on success creates a token in the personal_access_tokens table. The logout controller then clears out this token.

VueJS SPA

The VueJs SPA is a little more involved but I have tried to keep things simple for this example. I used the Vue CLI to scaffold things installing the following packages:

I will assume you have some experience working with the above technologies to keep this post as short as possible but if you have any questions on this setup please feel free to create an issue on the repo.

Setting Up Axios

First set up the services folder to keep all the API related files. While this is not necessary I found it really useful when building out large-scale apps. Any endpoints you need to access are held in a service.js file, organized by each Laravel controller. So for example all auth methods are held in a single auth service file. Each service file imports the main API service which is where the SPA does all the handling of tokens and logs the user out if Laravel sends a 401 (unauthorized) response.

Sanctum requires you to make a request to /sanctum/csrf-cookie before the user can log in, to enable this there is an Axios request made on the login page using the mounted VueJS method.

Axios withCredentials

An important note is that you must set withCredentials to true when calling the create method. A XMLHttpRequest from a different domain cannot set cookie values for its domain unless withCredentials is set to true before making the request.

Protecting Routes in a Vue SPA

The method for protecting your application routes is fairly simple. In the router file there is a meta field requiresAuth it's a boolean held against every route you want to protect. Using the Vue router beforeEach method check for a valid token which is held in local storage if it exists then the user is allowed to view the page. I wrote about this in more detail over on Freecodecamp if you are interested to learn more on this approach.

Notes on CORS

As the SPA is usually running on a separate domain name to the API, you have to work with CORS. Julia Evans has posted some great sketches that explain this tricky subject:

Laravel 7.0 and up comes with CORS support built in. You will need to set allow_credentials to true in the CORS config in order for the CSRF token to work and once you go live change the allow_origins parameter to the SPA URL to keep things secure.

If you use the VueJs CLI (which I recommend) you can set it to proxy your API URL so that it respects localhost. This took a bit of figuring out but if you have your local version of Laravel running at sanctum-example.test then you add this in your vue.config.js file:

module.exports = {
  devServer: {
    proxy: "sanctum-example.test",
  },
};

With this in place, you then call your API endpoints using http://localhost:8080/ or whatever your SPA is running at via the Vue CLI and you will not get all the frustrating CORS errors that I initially encountered during SPA development.

Summary

I hope this short post and example projects will help explain my approach to building auth into a VueJS SPA with a Laravel API. For most projects Sanctum definitely feels like it has achieved what it set out to provide "a featherweight authentication system for SPAs and simple APIs".