Laravel 8 REST API Authentication using Sanctum 
Tags: laravel, authentication, sanctum, tutorial
Published: 2021-09-15 12:02:24

Sanctum is Laravel package for authentication for single page application(SPAs), mobile applications and basic token based APIs. 

For SPA authentication, Sanctum uses Laravel’s built in cookie based authentication services. Means while working with front end technologies like react, Angular Sanctum create cookie and save in browser by using this accomplish authentication. For token based Rest APIs, Sanctum create token and save in **personal_access_tokens** table. while authentication try to match with this table if token not found then authentication goes to failed.

Let’s install sanctum package first and then create a register, login, logout APIs and protect our routes.

###Installation:###
```
composer require laravel/sanctum
```
This command install package using composer.
```
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
```
Next run this command, it creates migration files for personal_access_token table and configuration files for sanctum. You can check this file in database->migrations folder named like 2019_12_14_000001_create_personal_access_tokens_table.php
```
php artisan migrate
```
Then run this command, this create a personal_access_token table in database in which Sanctum store API tokens.

###Configuration:###
Go to app->Http->Kernal.php and add given lines to apis array of middlewareGroups.
```
'api' => [
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    'throttle:api',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

```
Note: If you get too many attempts error while calling APIs multiple time. Then comment ‘throttle:api’ line and keep default as it is like below screenshot.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/60if2tikz9fkmwa32bwe.png)

Next go to UserModel.php file and add set below code so usermodel can use HasApiTokens to issue token.
```
use Laravel\Sanctum\HasApiTokens;
use HasApiTokens, HasFactory, Notifiable;
```
Note in my project hasFactory trait not autoloaded.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5v1siiu69oikcu4vqisq.png)
         
####Create Crontroller####
```php artisan make:controller Api\AuthController```
This command create authController in Api folder of controller’s folder. 

Set routes in routes->api.php file 
```
use App\Http\Controllers\Api\AuthController;
Route::post("/register",[AuthController::class,'register']);
Route::post("/login",[AuthController::class,'login']);
```
Let’s make register function in authController. in this new user and token creates and given to response.
```
public function register(Request $request){
    	$fields = $request->validate([
			'name' =>'required|string',
			'email'=>'required|string|email|unique:users,email',
			'password' =>'required|confirmed'
    	]);

    	$user = User::create([
    		'name'=>$fields['name'],
    		'email'=>$fields['email'],
    		'password'=>Hash::make($fields['password']),
    	]);

    	//create token
    	$token = $user->createToken('myapptoken')->plainTextToken;

    	$response = [
    		'status'=>true,
    		'message'=>'registered successfully!',
    		'data' =>[
    			'user'=>$user,
    			'token'=>$token
    		]
    	];
    	return response($response,201);
    }
```
And call api using postman as below:
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6whfbewcpsxk2g7jcl5u.png)

####Login Function:####
```
public function login(Request $request){
    	$fields = $request->validate([
			'email'=>'required|string|email',
			'password' =>'required|confirmed'
    	]);
    	//check email
    	$user = User::where('email',$fields['email'])->first();
    	//check password
    	if(!$user || !Hash::check($fields['password'],$user->password)){
    		return response(['status'=>false,'message'=>'invalid email or password'],401);
    	}

    	//create token
    	$token = $user->createToken('myapptoken')->plainTextToken;

    	$response = [
    		'status'=>true,
    		'message'=>'Login successful!',
    		'data' =>[
    			'user'=>$user,
    			'token'=>$token
    		]
    	];
    	return response($response,201);
    }
```
Call login api as below:
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lx65stdnl037lc11jpom.png)

Now Let’s create authenticate routes in api-routes file as below.
```
Route::group(['middleware'=>['auth:sanctum']],function(){
	Route::post("/logout",[AuthController::class,'logout']);
});
```
In above routes sanctum middleware validates token from Authorization header.

Let’s make function logout in authController. 
```
public function logout(Request $request){
    	auth()->user()->tokens()->delete();
    	$response = [
    		'status'=>true,
    		'message'=>'Logout successfully',
    	];
    	return response($response,201);
    }

```
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4lg03njzbyhwzfsc0pi3.png)

While token is not set/validate then will receive below response. 
```{
    "message": "Unauthenticated."
}```

Note: Set header Accept:application/json to get response in json for above apis and Authorization header with Bearer <Token>.