Laravel Sanctum
Tags: laravel, api, mobileauthentication, sanctum
Published: 2021-10-05 16:49:40

I want to build an authentication system for both WEB and Mobile using API. After searching for good framework, Finally I choose Laravel. It is well suited for my requirement and one of the best frameworks, large community and well documented.

In this article, I'll explain step by step flow that how to integrate Laravel Sanctum. Mainly I focus on API base authentication.

## Use cases
1. API Tokens
2. Web Authentication
3. You can use both (API Tokens & Web Authentication)

### API Tokens
Its generate a simple API token for your user without complication of OAuth. This token have expire very long time (years). All tokens store in single database table and authenticating incoming HTTP requests via the Authorization header which should contain a valid API token.

### Web Authentication
Laravel Sanctum  will only attempt to authenticate using cookies when the incoming request originates from your own frontend. When you call HTTP request, it will first check for an authentication cookie and, if none is present, Sanctum will then examine the Authorization header for a valid API token.

### You can use both (API Tokens & Web Authentication)
It's okay to use single service either API Tokens or Web Authentication, it doesn't mean that you should mandatory use both services. You can use anyway based on your requirement. 

#### Laravel installation
`composer create-project laravel/laravel laravel_sanctum`
after installation done, start server to check installation successfully done.
`php artisan serve`

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ulob5tiko21lghcv45i6.png)

On the latest version of Laravel has already include Laravel Sanctum. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3k6o11xtcifcqdfo0yiw.png)

However, If you are using old version of Laravel, You can do it manually. 

In your application's `composer.json` file does not include `laravel/sanctum` then add it on `composer.json' file and run command `composer update` **or** follow the link instructions [Larevel-sanctum](https://laravel.com/docs/8.x/sanctum#installation).

### Database config
Open `.env` file and add your database details, In my case I'm using MySQL.

<pre>

    DB_CONNECTION=mysql
    DB_HOST=127.0.0.1
    DB_PORT=3306
    DB_DATABASE=laravel_sanctum
    DB_USERNAME=root
    DB_PASSWORD=

</pre>

After database configuration done. Run the command `php artisan migrate`. it will create a default database tables from Laravel.

Now you should add Sanctum's middleware to your `api` middleware group at `app/Http/Kernel.php`.


<pre>
 protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
        'api' => [
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];
</pre>



Next, you should publish the Sanctum configuration and migration files using the `vendor:publish` Artisan command. The sanctum configuration file will be placed in your application's `config` directory:

<pre>
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
</pre>

And it will create migration file for personal access token

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

Sanctum allows you to issue API tokens / personal access tokens that may be used to authenticate API requests to your application. When making requests using API tokens, the token should be included in the `Authorization` header as a `Bearer` token.

To begin issuing tokens for users, your User model should use the `Laravel\Sanctum\HasApiTokens` trait:

<pre>
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;
}
</pre>


Create a controller for user authentication

<pre>
php artisan make:controller Authcontroller 
</pre>

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

it will AuthController, In the AuthController add the follow lines

Request
`use Illuminate\Http\Request;`

Response
`use Illuminate\Http\Response;`

This is for password encrpt
`use Illuminate\Support\Facades\Hash;`

Your user model
`use App\Models\User;`


### Register User
<pre>
public function register(Request $request)
{
	$fields = $request->validate([
		"name" => 'required|string',
		"email" => 'required|string|unique:users,email',
		"password" => 'required|string|confirmed'
	]);

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

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

	$response = [
		'user' => $user,
		'token' => $token,
	];

	return response($response, 201);
}

</pre>
 
### Login
<pre>
public function login(Request $request)
{
	$fields = $request->validate([
		"email" => 'required|string',
		"password" => 'required|string',
	]);

	// Check Email
	$where = ["email"=>$fields['email']];
	$user = User::where($where)->first();

	// Check Password
	if(!$user || !Hash::check($fields['password'], $user->password))
	{
	   return response([
		   'message' => "Bad credentials"
	   ],401);
	}

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

	$response = [
		'user'=>$user,
		'token'=>$token
	];

	return response($response,201);
}
</pre>


### logout
<pre>
public function logout(Request $request)
{
	auth()->user()->tokens()->delete();

	$response = [
		'message' => 'logged out'
	];

	return response($response,201);
}
</pre>



Now go to `routes\api.php` and config Public/Protected routes like as shown in below

<pre>
//Public routes
Route::post('/register', [AuthController::class,'register']);
Route::post('/login', [AuthController::class,'login']);


//Protected routes
Route::group(['middleware'=>['auth:sanctum']], function () {
    Route::post('/logout', [AuthController::class,'logout']);
});
</pre>

It time to call API's. For this demo I'm using Postman

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

This request I have sent without post data to check the validations, And you must set the `headers` otherwise you will encounter with errors. `Accept:Application\Json`

Let register an User

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

You are successfully configured `Laravel Sanctum`  :)

In the response you will receive personal access token. 


<!--login image-->

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

In this response you can notice that we have received token, Use that token for all protected services. You should pass that token in headers as bearer token for Authorization.

I also give an example for Logout.
 

<!--logout image without token-->
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jycjezugu0ypj8modea3.png)

If you hit protected API without token, That request is unauthorized. 


Now I added Bearer token in request, Then I'm successfully logout.
<!-- logout successfully -->
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a89uargfd9z6v6lt2j3a.png)
 

Please feel free to ask me anything on this topic!