I'm trying to implement Socialite package into my project. Here is my code which works fine. However it does duplicate entry in the database if the user logs out tries to log back in. Also I can't get the user's public name with $userData->name. It returns null.
Here is my controller;
namespace App\Http\Controllers;
use App\AuthenticateUser;
use App\AuthenticateUserListener;
use App\Http\Requests;
use Illuminate\Http\Request;
class SocialLoginsController extends Controller implements
AuthenticateUserListener
{
/**
* @param AuthenticateUser $authenticateUser
* @param Request $request
* @return \Symfony\Component\HttpFoundation\RedirectResponse
*/
public function socialLogin(AuthenticateUser $authenticateUser, Request $request)
{
$hasCode = $request->has('code');
return $authenticateUser->execute($hasCode, $this);
}
/**
* When a user has successfully been logged in...
*
* @param $user
* @return \Illuminate\Routing\Redirector
*/
public function userHasLoggedIn($user)
{
return redirect('student');
}
My user repository;
namespace App\Repositories;
use App\User;
class UserRepository {
public function findByUsernameOrCreate($userData)
{
return User::firstOrCreate([
'username' => $userData->name,
'email' => $userData->email,
]);
}
}
Authenticate User Class;
<?php namespace App;
use Illuminate\Contracts\Auth\Guard;
use App\Repositories\UserRepository;
use Laravel\Socialite\Contracts\Factory as Socialite;
class AuthenticateUser {
/**
* @var UserRepository
*/
private $users;
/**
* @var Socialite
*/
private $socialite;
/**
* @var Guard
*/
private $auth;
/**
* @param UserRepository $users
* @param Socialite $socialite
* @param Guard $auth
*/
public function __construct(UserRepository $users, Socialite $socialite, Guard $auth)
{
$this->users = $users;
$this->socialite = $socialite;
$this->auth = $auth;
}
/**
* @param boolean $hasCode
* @param AuthenticateUserListener $listener
* @return \Symfony\Component\HttpFoundation\RedirectResponse
*/
public function execute($hasCode, AuthenticateUserListener $listener)
{
if ( ! $hasCode) return $this->getAuthorizationFirst();
elseif($hasCode) {
$user = $this->users->findByUsernameOrCreate($this->getGoogleUser());
$this->auth->login($user, true);
return $listener->userHasLoggedIn($user);
}
}
/**
* @return \Symfony\Component\HttpFoundation\RedirectResponse
*/
private function getAuthorizationFirst()
{
return $this->socialite->driver('google')->redirect();
}
/**
* @return \Laravel\Socialite\Contracts\User
*/
private function getGoogleUser()
{
return $this->socialite->driver('google')->user();
}
}
I've been able to get this working by using very similar code to what you have here, except I've modified the findByUsernameOrCreate
method in your UserRepository
. I created a syncUserDetails
method that looks like this:
public function syncUserDetails($userData)
{
if ( $user = $this->userRecordExists($userData) )
{
$user->token = $userData->token;
$user->google_id = $userData->id;
$user->name = $userData->name;
$user->avatar = $userData->avatar;
$user->first_name = $userData->user['name']['givenName'];
$user->last_name = $userData->user['name']['familyName'];
$user->save();
return $user;
}
return $this->user->firstOrCreate([
'email' => $userData->email,
'token' => $userData->token,
'google_id' => $userData->id,
'name' => $userData->name,
'avatar' => $userData->avatar,
'first_name' => $userData->user['name']['givenName'],
'last_name' => $userData->user['name']['familyName']
]);
}
It checks if there is a user already in the db with a matching email:
private function userRecordExists($userData)
{
return $this->user->where('email', $userData->email)->first();
}
and if so, then matches it up with the new data and returns a user.
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With