ホーム > Laravel > How to authenticate APIs with Laravel (Sanctum) and Vue (Nuxt)
Laravel

How to authenticate APIs with Laravel (Sanctum) and Vue (Nuxt)

Thank you for your continued support.
This article contains advertisements that help fund our operations.

⇨ Click here for Laravel article table of contents ⇨ Click here for Vue article table of contents

Implementing API authentication using Laravel (Sanctum) and Nuxt's auth-module.

Introduction

What is Sanctum?

Sanctum is Laravel's simplest authentication package released from Laravel 8.

Previously, LaravelPassport was commonly used for API authentication packages, but it had too many features.

However, because it had too many features, it was difficult to use as the first choice.

With Sanctum, it is now possible to authenticate APIs more simply.

Laravel Sanctum Official

What is Nuxt-Auth-Module?

It is a standard package for storing authentication information in Nuxt.

This package is designed to make it easy to set up the Vue Auth-module package in Nuxt.

Nuxt Auth Official

Overview of the Process

①Issuing a token for authentication in Laravel

②Storing the token in Nuxt-auth

This is the flow.

Let's first configure it on the Laravel side.

Laravel Configuration

Install the necessary components via commands.

Creating a project

composer create-project laravel/laravel laravel-api

Installing Sanctum

composer require laravel/sanctum

Setting up a local server

php artisan serve

The local server is set up:

Starting Laravel development server: http://127.0.0.1:8000

Allowing modification of the configuration file

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

A new file has been added to database/migrations which allows modification of personal_access_tokens.

Creating a database to store tokens

Create the personal_access_tokens table (by running the previous command).

Command:

php artisan migrate

If this command fails, it means there is an issue with the database connection.

Package Versions

"laravel/framework": "^8.75",
"laravel/sanctum": "^2.14",

Changes in App/Http/Kernel.php

Uncomment the commented part in the 'api' item around line 42:

'api' => [
  \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
  'throttle:api',
  \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

Changes in App/Http/Middleware/VerifyCsrfToken.php

    protected $except = [
      'api/login'
    ];

This allows POST for login without authentication.

Configuring APItoken authentication in User model

Make sure that such a configuration is present in the User model.

Most likely, this is automatically done via commands.

App/Models/User.php

use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;
  //Other code lines here

Creating Test User Data

Create test user data using the Seeder functionality.

How to prepare test data in Laravel (using Seeders)

Create a Seeder file via command

php artisan make:seeder UsersTableSeeder

database/seeders/UsersTableSeeder.php

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
//↓3 lines added
use Hash;
use DB;
use App\Models\User;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $data = [
            [
                'name' => 'laratechjp',
                'email' => 'laratech@example.com',
                'password' => Hash::make('password')
            ],
        ];
        DB::table('users')->insert($data);
    }
}

The Seeder above creates a user who can log in with:

email: laratech@example.com

password: password

Edit database/seeders/DatabaseSeeder.php

Only edit the necessary part:

    public function run()
    {
        $this->call(UsersTableSeeder::class);
        // \App\Models\User::factory(10)->create();
    }

Command

Load the classes you have set up:

composer dump-autoload

Generate Data

php artisan db:seed

Adding Login Functionality in Laravel

Creating login route

routes/api.php

use App\Http\Controllers\Api\Auth\LoginController;

Route::post('/login',[LoginController::class,'login']);

Basic routing in Laravel 8

Creating the login function

Assuming input fields for email and password:

Search for user by email ⇨ Compare stored password of the user

Writing the simplest function:

<?php

namespace App\Http\Controllers\Api\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

//Adding 2 lines
use Hash;
use Illuminate\Validation\ValidationException;

class LoginController extends Controller
{
    public function login(Request $request)
    {
        $email = $request->email;
        $password = $request->password;

        $user = User::where('email', $email)->first();

        if (! $user || ! Hash::check($password, $user->password)) {
            throw ValidationException::withMessages([
                'email' => ['Incorrect email or password'],
            ]);
        }

        $token = $user->createToken('token')->plainTextToken;
        return response()->json(compact('token'),200);
    }
}

As mentioned in the API token issuance section

Nuxt Configuration

Creating the project

yarn create nuxt-app nuxt-api

Running a local host via command

yarn dev

Local host is set up:

  Nuxt @ v2.15.8                      │
   │                                       │
   │   ▸ Environment: development          │
   │   ▸ Rendering:   server-side          │
   │   ▸ Target:      static               │
   │                                       │
   │   Listening: http://localhost:3000/

Installing nuxt-axios

Command:

yarn add @nuxtjs/axios

Adding nuxt-axios to nuxt.config.js

  modules: ["@nuxtjs/axios"],

Specifying the base URL for axios (in this case, the address of Laravel's local server)

Add to nuxt.config.js

  publicRuntimeConfig: {
    axios: {
      baseURL: process.env.BASE_URL,
    },
  },

Create a .env file

Create a file named .env at the root of the Nuxt project directory.

Add the following to .env:

BASE_URL=http://127.0.0.1:8000

Creating a login form

Create a pages/login/index.vue file

For those not using Vuetify, replace v-text-field with input tags.

<template>
  <v-row>
    <v-col class="text-center">
      <v-text-field label="email" v-model="email"></v-text-field>
      <v-text-field label="password" v-model="password"></v-text-field>
      <v-btn @click="login" color="blue" outlined>Login</v-btn>
    </v-col>
  </v-row>
</template>

<script>
  export default {
    data() {
      return {
        email: "",
        password: "",
      }
    },
    methods: {
      login() {
        console.log("clicked")
        this.$axios
          .$post("/api/login", {
            email: this.email,
            password: this.password,
          })
          .then(response => {
            console.log(response)
          })
      },
    },
  }
</script>

Trying to login

Enter:

laratech@example.com password

and click the button

If a token is returned in the console, it means the login was successful.

{token: '6|XTSYN6HylafFkHfgWHxoODrrfA3kDjlptQFPChaB'}

This completes the confirmation of operation.

The next step is to use the token in Nuxt to create an authentication feature.

Using nuxt-auth-module

Installing the package via command

Instructions can be found here

yarn add @nuxtjs/auth-next

Adding to nuxt.config.js

Make sure to consolidate the modules' settings within the modules list, which may already have axios added:

  modules: ["@nuxtjs/axios", "@nuxtjs/auth-next"],
  //Modules: https://auth.nuxtjs.org/schemes/local
  auth: {
    strategies: {
      local: {
        token: {
          property: "token",
          global: true,
        },
        user: {
          property: "user",
        },
        endpoints: {
          login: { url: "/api/login", method: "post" },
          logout: { url: "/api/logout", method: "post" },
          user: { url: "/api/user", method: "get" },
        },
      },
    },
  },

Displaying user information in Nuxt

When using in template

<template>
  <div>
    <p>{{ $auth.loggedIn }}</p>
    <p>{{ $auth.user }}</p>
  </div>
</template>

Display:

true (when authenticated, false when not authenticated)

{ "id": 1, "name": "laratechjp", "email": "laratech@example.com", ... }

When using in script

Just use this:

<script>
export default {
  created(){
    console.log(this.$auth.user)
  }
}
</script>

Writing Processes that Only Users Not Logged In Can Access

Laravel

Add settings to .env

Specify the Nuxt path in .env:

SESSION_DOMAIN=http://127.0.0.1:3000
SANCTUM_STATEFUL_DOMAINS=http://127.0.0.1:3000

After changing .env, run the command:

php artisan config:cache

The changes will be reflected in config/session.php and config/sanctum.

Update api.php

Add a line for post:

Route::group(['middleware' => 'auth:sanctum'],function(){
    Route::get('/user',[UserController::class,'index']);
    Route::post('/post',[PostController::class,'store']);
});

Create the controller

php artisan make:controller Api/PostController

Write in App/Http/Controller/Api/PostController.php

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function store(Request $request)
    {
        $content = $request->content;
        $user = $request->user();
        return response()->json(compact('content','user'),200);
    }
}

Nuxt

<template>
  <v-btn @click="post">Post!</v-btn>
</template>
<script>
  export default {
    data() {
      return {
        content: "Test post",
      }
    },
    methods: {
      post() {
        this.$axios
          .$post("/api/post", {
            content: this.content,
          })
          .then(response => {
            console.log(response)
          })
      },
    },
  }
</script>

Result:

content: "Test post",
user: {id: 1, name: 'laratechjp', email: 'laratech@example.com', ....

That's it, well done!

Conclusion

That's all.

I have posted the code on GitHub:

Laravel の GitHub

Nuxt の GitHub

For feedback or complaints, please contact me via Youtube Comment!

Thank you and goodbye!

Top Articles:

Deploying a PHP7.4 + Laravel6 Project to AWS EC2

Implementing Breadcrumbs in Laravel with laravel-breadcrumbs

Please Provide Feedback
We would appreciate your feedback on this article. Feel free to leave a comment on any relevant YouTube video or reach out through the contact form. Thank you!