I am working in Laravel authentication login using socialite. Now I can able to save data of user from socialite. But now I am facing problem how to authenticate user from gmail, github.
After some research I understood that I need to create custom authentication. I googled but all are Laravel 4.1 topics. If any one work on this please provide your answers.
I already read following topics but I didn't got how to do it?
http://laravel.com/docs/5.1/authentication#social-authentication
http://laravel.com/docs/5.1/providers
http://laravel-recipes.com/recipes/115/using-your-own-authentication-driver
http://laravel.io/forum/11-04-2014-laravel-5-how-do-i-create-a-custom-auth-in-laravel-5
Update
public function handleProviderCallback() {
$user = Socialite::with('github')->user();
$email=$user->email;
$user_id=$user->id;
//$authUser = User::where('user_id',$user_id)->where('email', $email)->first();
$authUser = $this->findOrCreateUser($user);
if(Auth::login($authUser, true)) {
return Redirect::to('user/UserDashboard');
}
}
private function findOrCreateUser($user) {
if ($authUser = User::where('user_id',$user->id)->first()) {
return $authUser;
}
return User::create([
'user_id' => $user->id,
'name' => $user->nickname,
'email' => $user->email,
'avatar' => $user->avatar
]);
}
This answer is most suited for Laravel 5.1. Please take care if you are in some other version. Also keep in mind that IMHO this is a rather advanced level in Laravel, and hence if you don't fully understand what you are doing, you may end up crashing your application. The solution is not end to end correct. This is just a general guideline of what you need to do in order for this to work.
Hint: Laravel documentation for this topic is here.
Hint2: The last link you mentioned is quite useful in my opinion. I learned all of this after reading that link.
http://laravel.io/forum/11-04-2014-laravel-5-how-do-i-create-a-custom-auth-in-laravel-5
Before we start, I would first like to describe the login flow which will help you understand the process. Laravel uses a driver
to connect to the database to fetch your records. Two drivers come pre-bundled with laravel - eloquent
& database
. We want to create a third so that we can customize it to our needs.
Illuminate\Auth\Guard
inside your vendor folder is the main file which has code for the user to log in and log out. And this file mainly uses two Contracts (or interfaces)
that we need to override in order for our driver to work. From Laravel's own documentation read this:
The Illuminate\Contracts\Auth\UserProvider implementations are only responsible for fetching a Illuminate\Contracts\Auth\Authenticatable implementation out of a persistent storage system, such as MySQL, Riak, etc. These two interfaces allow the Laravel authentication mechanisms to continue functioning regardless of how the user data is stored or what type of class is used to represent it.
So the idea is that for our driver to work we need to implement Illuminate\Contracts\Auth\UserProvider
and Illuminate\Contracts\Auth\Authenticatable
and tell Laravel to use these implementations instead of the defaults.
So let's begin.
Step 1:
Choose a name for your driver. I name mine socialite
. Then in your config/auth.php
, change the driver
name to socialite
. By doing this we just told laravel to use this driver for authentication instead of eloquent
which is default.
Step 2:
In your app/Provider/AuthServiceProvider
in the boot()
method add the following lines:
Auth::extend('socialite', function($app) {
$provider = new SocialiteUserProvider();
return new AuthService($provider, App::make('session.store'));
});
What we did here is:
Auth
facade to define the socialite
driver.SocialiteUserProvider
is an implementation of UserProvider
.AuthService
is my extension of Guard
class. The second parameter this class's constructor takes is the session which laravel uses to get and set sessions.Guard
class instead of the default one.Step 3:
Create SocialiteUserProvider
. If you read the Laravel's documentation, you will understand what each of these methods should return. I have created the first method as a sample. As you can see, I use my UserService
class to fetch results. You can fetch your own results however you want to fetch them. Then I created an User
object out of it. This User
class implements the Illuminate\Contracts\Auth\Authenticatable
contract.
<?php
namespace App\Extensions;
use App\User;
use App\Services\UserService;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider;
class SocialiteUserProvider implements UserProvider
{
private $userService;
public function __construct(UserService $userService)
{
$this->userService = $userService;
}
public function retrieveById($identifier)
{
$result = $this->userService->getUserByEmail($identifier);
if(count($result) === 0)
{
$user = null;
}
else
{
$user = new User($result[0]);
}
return $user;
}
public function retrieveByToken($identifier, $token)
{
// Implement your own.
}
public function updateRememberToken(Authenticatable $user, $token)
{
// Implement your own.
}
public function retrieveByCredentials(array $credentials)
{
// Implement your own.
}
public function validateCredentials(Authenticatable $user, array $credentials)
{
// Implement your own.
}
}
Step 4:
Create User
class which implements the Authenticatable
. This class has to implement this interface because the Guard
class will use this class to get values.
<?php
namespace App;
use Illuminate\Contracts\Auth\Authenticatable;
class User implements Authenticatable
{
protected $primaryKey = 'userEmail';
protected $attributes = [];
public function __construct(array $attributes)
{
$this->attributes = $attributes;
}
public function getUserAttributes()
{
return $this->attributes;
}
public function getAuthIdentifier()
{
return $this->attributes[$this->primaryKey];
}
public function getAuthPassword()
{
// Implement your own.
}
public function getRememberToken()
{
// Implement your own.
}
public function setRememberToken($value)
{
// Implement your own.
}
public function getRememberTokenName()
{
// Implement your own.
}
}
Step 5:
Finally create the AuthService class that will call the Guard
methods. This is my own implementation. You can write your own as per your needs. What we have done here is extended the Guard
class to implement two new functions which are self explanatory.
<?php
namespace App\Services;
use Illuminate\Auth\Guard;
class AuthService extends Guard
{
public function signin($email)
{
$credentials = array('email' => $email);
$this->fireAttemptEvent($credentials, false, true);
$this->lastAttempted = $user = $this->provider->retrieveById($email);
if($user !== null)
{
$this->login($user, false);
return true;
}
else
{
return false;
}
}
public function signout()
{
$this->clearUserDataFromStorage();
if(isset($this->events))
{
$this->events->fire('auth.logout', [$this->user()]);
}
$this->user = null;
$this->loggedOut = true;
}
}
Step 6: Bonus Step
Just to complete my answer, I will also explain the structure that UserService
class expects. First lets understand what this class does. In our above steps we created everything to let laravel know how to use our authentication driver, instead of theirs. But we still haven't told laravel that how should it get the data. All we told laravel that if you call the userService->getUserByEmail($email)
method, you will get your data. So now we simply have to implement this function.
E.g.1 You are using Eloquent
.
public function getUserByEmail($email)
{
return UserModel::where('email', $email)->get();
}
E.g.2 You are using Fluent
.
public function getUserByEmail($email)
{
return DB::table('myusertable')->where('email', '=', $email)->get();
}
Thank you @skittles for pointing out that I have not clearly shown where the files should be placed. All the files are to be placed as per the namespace given. E.g. if the namespace is App\Extensions
and the class name is SocialiteUserProvider
then location of file is App\Extensions\SocialiteUserProvider.php
. The App
directory in laravel is the app
folder.
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