5

It's been several days now that I spend on Laravel Sanctum trying to figure out how I can set up my authentication system.

Context

I'm building a tickets web app for my company and for this i decided to build an API and a React frontend app that consumes the API. End-users of the app need an account to manage tickets so i create an user table in the database and create several routes for the API to create, delete and update users. To manage users api authentication, i decided to use Laravel Sanctum and his built-in SPA authentication system that is session based.

For that, i follow the guide and setup all the needs to ensure that the frontend is ready to work with laravel sanctum. Here my Kernel.php for the api middlewares :

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

And the routes in web.php to login / logout the user through Laravel Sanctum SPA authentication.

<?php
use App\Http\Controllers\UserController;
use Illuminate\Support\Facades\Route;

Route::post('/login', [UserController::class, 'login']);
Route::get('/logout', [UserController::class, 'logout']);

Problem

I have to build a non-web application, in particular a windows-service that needs to fetch data in a dabatase and use the /api/tickets endpoint of the API with POST method to create a new ticket with these data.

I know that this futur windows-service is not a front-end app so i can't use the SPA authentication system. Instead, i want to use tokens with Laravel Sanctum to authenticate the service.

My questions are :

  • How i can achieve this and seperate the users authentication and the service authentication.
  • As my api contains http://myapi.net/login et http://myapi.net/logout for end-users authentication, do i need to create something like api/auth/service route for sending and deleting token ?
  • Should i create a new table called service in my database or stay with user table ?
adrien
  • 115
  • 1
  • 6

1 Answers1

5

I am working in a project with a similar context. What I have done is establish user profiles based on the use they are allowed to make of the API. Use the Sanctum token abilities for this: https://laravel.com/docs/8.x/sanctum#token-abilities

  1. Ensure your User class extends Authenticable:
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;
}
  1. Create API routes and controller methods for your service profile authentication where you assign some type of special token abilities you need:
$token = $user->createToken('app-token', ['service'])->plainTextToken;

...where 'service' will be the ability that you will check. Return this token in the /login endpoint as API-KEY.

  1. On each service API path, verify authentication using the Sanctum middleware:
Route::middleware('auth:sanctum')->post('/updatesomething', 'something@update');
  1. Within the controller methods, verify the token abilities to prevent web users from making use of them or vice versa. Ideally you can create a new middleware with this logic to apply to these routes.
public function update(Request $request){
        if ($user->tokenCan('service')) {
        //do allowed actions to user profile 'service'
    }
}

In this way, you can now consume your API with a 'service' profile and authenticated for this purpose using the token received in /login in the following requests. You should include it in a header like 'Bearer Token'. Optionally you can create a logout method in your API and revoke the token when you see fit:

$user->tokens()->delete();
jssDev
  • 923
  • 5
  • 18
  • Hi jssDev! Sorry to take so long to answer, I was away on vacation and when I came back I didn't think to return quickly on the thread. So basically i understand your proposal and i think i'm going to work with this. I have just one question : My service doesn't need an email for authentication while user (end-user) needs one, so i need to create an other Authenticatable model for the services right ? – adrien Aug 05 '21 at 12:18
  • Hi Adrien! Sorry for the delay, but this time it was me who was on vacation :) I think it is not necessary to create a new model. Just try to get the user uniquely (maybe through the user id) in your login controller method. In response, you must return this user object in addition to the authentication token. – jssDev Sep 01 '21 at 10:40