Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Socialite Google Register and Login

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();

}



}
like image 484
mergenc Avatar asked Mar 02 '15 19:03

mergenc


Video Answer


1 Answers

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!

like image 168
Jesse Schutt Avatar answered Sep 19 '22 14:09

Jesse Schutt