Laravel — Implementing Social Auth for API (via mobile app) with Socialite & Passport
While I was developing an API for a mobile app, I faced the issue of how I could implement a social authentication (Facebook, Google) between our mobile app and our API.
I knew about Laravel’s Socialite package for implementing that in the web (with redirects and callbacks…) but I was not familiar of doing that using an API.
After some search and testing I figured out the best way of doing this, with best practises and security in mind.
This is a clear and complete implementation flow and example, of how I achieved that easily with Laravel, Laravel Passport and Laravel Socialite.
TL;DR
The flow is simple:
- In the mobile app, you use the specific SDK’s for user authentication.
- Using the SDK’s you get an access token for that user.
- You send a request to the mobile app’s API (login route) with the access token in a parameter.
- You get the access token and re-authenticate it in the backend using Socialite package:
Socialite::driver('facebook')->userFromToken($access_token);
- If the access_token exists and is correct, you get the user’s info (provider’s user), and continue your logic (e.g create or login the user).
Complete Example (Laravel 8)
Notice: I included only the necessary files and changes. I skipped the setup process of Laravel, Passport, Socialite and extra checks, try-catch blocks etc. I tried to make the example for begginers too. The example shows the implementation for Facebook auth, but it is the same for other providers like Google.
config/services.php
'facebook' => [
'client_id' => env('FACEBOOK_CLIENT_ID'),
'client_secret' => env('FACEBOOK_CLIENT_SECRET'),
'redirect' => env('FACEBOOK_REDIRECT_URI')
],
.env file
FACEBOOK_CLIENT_ID={the_facebook_client_id}
FACEBOOK_CLIENT_SECRET={the_facebook_client_secret}
FACEBOOK_REDIRECT_URI=
Notice: Apparently the redirect URI is not needed!
Database setup
In the create_users_table migration file
- we make the user email and password nullables
- we add provider_name and provider_id.
Schema::create('users', function (Blueprint $table) {
...
$table->string('email')->unique()->nullable();
$table->string('password')->nullable();
...
$table->string('provider_name')->nullable();
$table->string('provider_id')->nullable();
...
});
Route
use App\Http\Controllers\AuthController;...Route::get('social/login', [AuthController::class, 'socialLogin']);
App\Http\Controllers\AuthController.php
/**
* Social Login
*/
public function socialLogin(Request $request)
{
$provider = "facebook"; // or $request->input('provider_name') for multiple providers
$token = $request->input('access_token'); // get the provider's user. (In the provider server)
$providerUser = Socialite::driver($provider)->userFromToken($token); // check if access token exists etc.. // search for a user in our server with the specified provider id and provider name
$user = User::where('provider_name', $provider)->where('provider_id', $providerUser->id)->first(); // if there is no record with these data, create a new user
if($user == null){
$user = User::create([
'provider_name' => $provider,
'provider_id' => $providerUser->id,
]);
} // create a token for the user, so they can login
$token = $user->createToken(env('APP_NAME'))->accessToken; // return the token for usage
return response()->json([
'success' => true,
'token' => $token
]);
}
I hope this helps! Thanks for reading!
John Stavropoulos
Connect with me here:
- Linkedin: https://www.linkedin.com/in/ioannis-stavropoulos/
- Github: https://github.com/j8n
- Twitter: https://twitter.com/Stavropoulos91
Check out our software dev agency.