Laravel API Authentication via Sanctum & Socialite and test on Postman
Published: 2022-08-18 16:51:00

**Laravel Sanctum with Socialite API**

**(Updated on 23/9/2022 : Flutter app updated)**

Hello everyone, this is my first post on [DEV.to](https://dev.to/).
In this post, I will show you how to implement Laravel Sanctum with Socialite in a very basic way.

So let's get started. 

**1. Create a new Laravel project:**
**Step 1:** Open your terminal OR command prompt and run this command:

`composer create-project laravel/laravel test`

Or by this command:

`laravel new test`

**Step 2:** Create a new DB, then go to your `.env` file and add your database details.
For example:

```
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db_name
DB_USERNAME=root
DB_PASSWORD=
```
**2. Install Laravel Sanctum Package:**

**Step 1:** Install Laravel Sanctum via the Composer:
`composer require laravel/sanctum`

**Step 2:** You should publish the Sanctum configuration and migration files using the `vendor:publish` Artisan command:

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

**Step 3:** Uncomment the Sanctum middleware in `app/Http/Kernel.php` file :

```php
'api' => [
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
```
**Step 4:** Go to the users table and set `password` to `nullable()` as Laravel Socialite does not need a password:

```php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password')->nullable();
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
};

```
**Step 5:** Now we need to create an AuthController to handle users sign-in and sign-up:
`php artisan make:controller AuthController`

This is a very simple Auth controller with two functions `register` and `login`:

```php
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Auth;

class AuthController extends Controller
{
    public function register(Request $request)
    {
        $validator = Validator::make($request->only('name', 'email', 'password', 'password_confirmation'), [
            'name' => ['required', 'min:2', 'max:50', 'string'],
            'email' => ['required', 'email', 'unique:users,email'],
            'password' => ['required', 'min:6', 'max:255', 'confirmed', 'string'],
        ]);
        if ($validator->fails())
            return response()->json($validator->errors(), 400);
        $input = $request->only('name', 'email', 'password');
        $input['password'] = Hash::make($request['password']);
        $user = User::create($input);
        $data =  [
            'token' => $user->createToken('Sanctom+Socialite')->plainTextToken,
            'user' => $user,
        ];
        return response()->json($data, 200);
    }

    public function login(Request $request)
    {
        $validator = Validator::make($request->only('email', 'password'), [
            'email' => ['required', 'email', 'exists:users,email'],
            'password' => ['required', 'min:6', 'max:255', 'string'],
        ]);
        if ($validator->fails())
            return response()->json($validator->errors(), 400);
        if (Auth::attempt(['email' => $request->email, 'password' => $request->password])) {
            $user = $request->user();
            $data =  [
                'token' => $user->createToken('Sanctom+Socialite')->plainTextToken,
                'user' => $user,
            ];
            return response()->json($data, 200);
        }
    }
}

```

**3. Install Laravel Socialite Package:**
**Step 1:** To get started with Socialite, use the Composer package manager to add the package to your project's dependencies:
`composer require laravel/socialite`

**Step 2:** Before using Socialite, you will need to add credentials for the OAuth providers your application utilizes,(In my case it's Google), So go to `config/services.php` and add this code:

```php
'google' => [
        'client_id' => env('GOOGLE_CLIENT_ID'),
        'client_secret' => env('GOOGLE_CLIENT_SECRET'),
        'redirect' => 'GOOGLE_REDIRECT_URI',
    ],
```
_**Remember that this will only work for Google tokens**_.
Since you are building API you don't need to set anything in your `.env` file to let socialite work.

**Step 3:** To keep things organized you need a new controller to handle login via provider, So we will create it:

`php artisan make:controller SocialiteController`

Now we need to make two functions `handleProviderCallback` to handle the login and `validateProvider` to check what provider used:

```php
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Laravel\Socialite\Facades\Socialite;
use Illuminate\Support\Facades\Validator;

class SocialiteController extends Controller
{
    public function handleProviderCallback(Request $request)
    {
        $validator = Validator::make($request->only('provider', 'access_provider_token'), [
            'provider' => ['required', 'string'],
            'access_provider_token' => ['required', 'string']
        ]);
        if ($validator->fails())
            return response()->json($validator->errors(), 400);
        $provider = $request->provider;
        $validated = $this->validateProvider($provider);
        if (!is_null($validated))
            return $validated;
        $providerUser = Socialite::driver($provider)->userFromToken($request->access_provider_token);
        $user = User::firstOrCreate(
            [
                'email' => $providerUser->getEmail()
            ],
            [
                'name' => $providerUser->getName(),
            ]
        );
        $data =  [
            'token' => $user->createToken('Sanctom+Socialite')->plainTextToken,
            'user' => $user,
        ];
        return response()->json($data, 200);
    }

    protected function validateProvider($provider)
    {
        if (!in_array($provider, ['google'])) {
            return response()->json(["message" => 'You can only login via google account'], 400);
        }
    }
}

```
**Step 4:** We need now to create our API routes, So go to `routes/api.php` and add these routes:

```php
use App\Http\Controllers\AuthController;
use App\Http\Controllers\SocialiteController;
Route::controller(AuthController::class)->group(function () {
    Route::post('/', 'register');
    Route::post('/login', 'login');
});

Route::post('/login/callback', [SocialiteController::class, 'handleProviderCallback']);
```
**Step 5:** Run:
`php artisan migrate`
And:
`php artisan serv`

Now that we've finished the code, let's go to Postman and test our routes:
**Test normal register and login**:
**register**:
![Normal Regist](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1hrpq7nci8d61aq124gb.PNG)

**Via Socialite**:

![via Laravel Socialite](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qlpy5839p3y4xhuv4jhw.PNG)

You may now be wondering how to get **access_provider_token**, well I'm using a Flutter application created by my friend [Fadi Asfour](https://www.linkedin.com/in/fadi-asfour) to get these tokens.

Some images from the Flutter app:



![sign-in](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3i1xzc9p0vk2v86rqqsb.jpg)
And here is the Google token:


![Google Token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tralapdlftbuhfft9gsc.jpg)
You can download the app from [HERE]
(https://www.mediafire.com/file/z1o69j0xizklrlm/Get_Access_Token.apk/file)
**Or** get the token online from this [SITE](https://fadi-asfour.github.io/get_access_token)
You can see all user info given by Google token by `dd` the `$providerUser` in `SocialiteController`:
![All user info](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lenhhvojod60i1nvfym8.PNG)

**You can get the source code for this project from [Github](https://github.com/Philip-Droubi/Laravel-Sanctum-Socialite-example)**

In the end, I hope this article is useful and helpful to you, and remember that this is just a very simple form of the code so that the article is not too long, so try to add what you need (for example `Providers Table`), and link each user registered by Laravel Socialite to this table and record the user Provider and other details, and do not forget your touch.

If you have any questions, please feel free to comment on this post.