Laravel Sanctum with Socialite API
(Updated on 23/9/2022 : Flutter app updated)
Hello everyone, this is my first post on 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 :
'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
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
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:
'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
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:
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:
Via Socialite:
You may now be wondering how to get access_provider_token, well I'm using a Flutter application created by my friend Fadi Asfour to get these tokens.
Some images from the Flutter app:
You can download the app from HERE
Or get the token online from this SITE
You can see all user info given by Google token by dd
the $providerUser
in SocialiteController
:
You can get the source code for this project from Github
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.
Top comments (11)
Great article, I really need this.
Also, thanks for sharing the Flutter app.
@philipdroubi , Do I need to create a Google app to get client_id and client_secret ?
And does this work with Facebook, Github and other providers??
@rober You're welcome.
1- As a backend you don't need to create any google app, frontend should do.
2- Yes it works, But you need to edit your
config/services.php
file to be like this :And the
validateProvider
function inSocialiteController
to be like this :You saved my day.
Cheers mate!
My pleasure! 😃
where can i find the access_provider_token ?
The redirect is not obligatory?
@229okpe
You can get the access_provider_token for testing purpose through this flutter app or through this website.
And remember that as an API the frontend application must send the access_provider_token through the request.
No need for any redirect.
is there no providers table to know which this user comes from google ,GitHub or Facebook ??
and how mobile developer sends me access_token_provider in callback ??
@ahmedali190000
1- Yes, of course, if you want to store from which provider each user came from, you must have a
providers_table
.2- Mobile developers can send you the
access_token_provider
in the request parameters or body, but if you mean the token itself it's better to send it using the request body as it may be too long to be in the request parameters.Bro!, Thank you!
@keyvervelasquez You're welcome.