Problem with authenticating user using laravel socialite - php

I'm trying to make login with google using laravel socialite and I have a problem.
Route that initiates login:
Route::get('/auth/login/google', 'AuthController#google');
Method in controller that initiates login:
public function google()
{
return Socialite::driver('google')->redirect();
}
Callback route:
Route::get('/auth/login/google/redirect', 'AuthController#googleRedirect');
Callback method in controller:
public function googleRedirect()
{
$googleUser = Socialite::driver('google')->user();
$email = $googleUser->getEmail();
$user = new User();
$user = $user->firstOrCreate(['email' => $email], ['email' => $email, 'password' =>
bcrypt(str_shuffle('abcdefgh45678')), 'email_verified' => 1]);
Auth::login($user, true);
}
And I'm getting ERR_EMPTY_RESPONSE every time I'm trying to redirect user after login.
Funny thing is that I can dump data with dd(Auth::user()->id) and I'm getting user's ID, but when I try to redirect user to the home page using return redirect('/') I'm getting empty response error and if I manually go to home page my user is not authenticated.

#Matej Petric blow code is working for me.
public function handleProviderCallback($provider) {
$user = Socialite::driver('google')->stateless()->user();
$authUser = $this->findOrCreateUser($user);
if ($authUser) {
Auth::login($authUser, true);
return redirect('/');
} else {
return redirect('/login')->withErrors(['msg', 'The Message']);
}
}
public function findOrCreateUser($user) {
$authUser = User::where('email', $user->email)->first();
if ($authUser) {
return $authUser;
}
$userN = User::create([
'name' => $user->name,
'email' => $user->email,
'password' => bcrypt(generateRandom()),
]);
return $userN;
}

Related

Laravel login with Socialite (google, facebook, etc) and create an access token of my own app

I am using Laravel Social Authentication with Socialite, I can login successful, but I want to create the access token of my own app, but not the google, twitter and facebook token.
I can create the access token, but it creates everytime when the user login with Socialite. What I want is the token will be created when the user first login with Socialite. Also, the 'user_id' is missing when the token created.
Here's my loginController
public function handleProviderCallback($provider)
{
try {
$user = Socialite::driver($provider)->stateless()->user();
} catch (Exception $e) {
return redirect('/login');
}
$authUser = $this->findOrCreateUser($user, $provider);
Auth::login($authUser,false);
$user = User::find($authUser['user_id']);
return $this->getBearerTokenByUser($user, 3, true);
// return redirect($this->redirectTo);
return $user;
}
public function findOrCreateUser($providerUser, $provider)
{
$account = SocialProvider::whereProviderName($provider)
->whereProviderId($providerUser->getId())
->first();
if ($account) {
return $account->user;
} else {
$user = User::whereEmail($providerUser->getEmail())->first();
if (! $user) {
$user = User::firstOrCreate([
'email' => $providerUser->getEmail(),
'first_name' => $providerUser->getName(),
]);
}
$user->socialProviders()->create([
'provider_id' => $providerUser->getId(),
'provider_name' => $provider,
]);
return $user;
}
Here is the database data table 'oauth_access_tokens'
table 'users_key'
The user_id is missing and the tokens were created twice for the same person (login with google).
The user doesn't have the password because it authentication with Socialite.
you might wanna do some thing like
// Retrieve user by email, or create it with the email and first_name attributes...
User::firstOrCreate(
['email' => $providerUser->getEmail()],
['first_name' => $providerUser->getName()]
]);

Laravel 5.7 Auth::login($findUser, true) returns null

I'm trying to login a user through laravel socialite. Everything is working fine but the user is not getting logged in!
I'm getting response from facebook, saving the response in the database and trying to login after that.
here is the code:
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Laravel\Socialite\Two\InvalidStateException;
use Auth;
use Socialite;
use App\User;
use DB;
use Log;
public function handleProviderCallback($provider)
{
$social = Socialite::driver($provider)->user();
$findUser = User::where('email', $social->email)->first();
if ($findUser) {
// dd($findUser); **************** This returns information of the user who is trying to login through facebook
// dd(Auth::login($findUser, true)); ***************** This line returns null
if (Auth::login($findUser, true)) {
// dd(Auth::loginUsingId($findUser->id, true));
redirect()->route('dashboard');
} else {
return 'Error'; //**************** This get echoed on the screen
}
} else {
$user = new User();
$user->name = $social->name;
$user->email = $social->email;
$user->avatar = $social->avatar;
$user->provider = $provider;
$user->id = $social->id;
$user->password = bcrypt('password');
$user->save();
}
if (Auth::login($user)) {
return redirect()->intended('/home');
} else {
return 'Error';
}
}
Neither register, nor login is working.
The login() method doesn't return anything so if (Auth::login($findUser, true)) will never pass.
Also, it might be worth using the firstOrCreate() to make your method smaller:
public function handleProviderCallback($provider)
{
$social = Socialite::driver($provider)->user();
User::unguard();
$user = User::firstOrCreate([
'email' => $social->email,
], [
'id' => $social->id,
'name' => $social->name,
'avatar' => $social->avatar,
'provider' => $provider,
'password' => bcrypt('password'),
]);
auth()->login($user, true);
return redirect()->intended('/home');
}
If you want to check if the User is signed in then you can use the auth()->id() method to retrieve the current authenticated user's id and then compare that to the $user->id:
if (auth()->id() !== $user->id) {
return 'Error';
}
Obviously, if you prefer to use the Auth facade instead of the auth() helper function then you can use Auth::id() instead of auth()->id()

User authentication via curl request

I've got same login page for every CRM.
These are the steps:
Enter password and login
Send curl to CRM on crm.dev/api/auth/check with user data, which checks if user exists in CRM
CRM returns success if user exists, after this authenticates user via Auth::user('user_data_here') and redirects to main page of CRM
My problem is that auth doesn't work. And no user data is stored in session (because of previous problem).
CRM auth code:
public function checkUserExists(Request $request)
{
$this->redirectIfAuthorized();
$user = User::find($request->uid);
if ($user) {
return ['response' => 'LOGIN_SUCCESS'];
}
return ['response' => 'DB_ERROR'];
}
public function login(Request $request)
{
$this->validateLogin($request);
$user = User::find($request->uid);
$user->remember_token = $request->token;
if ($user->update()) {
Auth::login($user, true);
return redirect()->intended($this->redirectPath());
} else {
return redirect($this->redirectAfterLogout);
}
}
public function redirectIfAuthorized()
{
if (Auth::check()) {
return redirect($this->redirectTo);
}
}
Api route:
Route::group(['prefix' => 'auth'], function () {
Route::post('check', 'LoginController#checkUserExists');
Route::get('login', 'LoginController#login');
Route::get('logout', 'LoginController#logout');
});
And login page's logic for this CURL request
private function sendToken($action, $user, $token)
{
$query = DB::table('user_base')->join('bases', 'bases.id', '=', 'user_base.base_id')
->where('user_base.user_id', $user);
$result = $query->get();
foreach ($result as $row) {
$urlAPI = $row->url_api;
if ($urlAPI == 'http://appliance.dev/api/auth') {
$urlAPI .= '/check';
}
$rsp = $this->curl($urlAPI, array(
'apiKey' => $this->apiKey,
$action => true,
'uid' => $row->base_uid,
'token' => $token
));
}
}
I needed to use routing in web.php file instead of api.php

Laravel email confirm login

Ok so what i'm trying todo, do not let login if user has not confirmed his account by email. My login code looks like that:
public function postLogin()
{
$credentials = [
'confirmed' => 0,
'email' => Input::get('email'),
'password' => Input::get('password')
];
$user = Sentinel::authenticate($credentials, false); // Login the user (if possible)
if ($user and $user->banned) {
Sentinel::logout();
$user = null;
}
if ($user) {
return $this->afterLoginActions();
} else {
$this->alertFlash(trans('app.access_denied'));
return Redirect::to('auth/login');
}
}
But i can still login without any errors. Any help? Thanks guys!
Edited: working, but now i dont get flash message if my details are incorect.
Code:
public function postLogin()
{
$credentials = [
'email' => Input::get('email'),
'password' => Input::get('password'),
'confirmed' => 1
];
$user = Sentinel::authenticate($credentials, false); // Login the user (if possible)
if ($user and $user->banned) {
Sentinel::logout();
$this->alertFlash(trans('app.banned'));
$user = null;
}
if ($user->confirmed==1) {
return $this->afterLoginActions();
}
else if ($user->confirmed==0) {
Sentinel::logout();
$this->alertFlash(trans('app.not_active'));
return Redirect::to('auth/login');
} else {
$this->alertFlash(trans('app.access_denied'));
return Redirect::to('auth/login');
}
}
Do you have a column in your table storing the information if this user passed the email confirmation? If you have one, this is what I do it with typical Laravel postLogin method.
public function postLogin(Request $request)
{
$credentialas = (your credential here);
// only check credentials
if ($this->guard()->once($credentials)) {
$currentStatus = $this->guard()->user()->status;
if (intval($currentStatus) === (NOT_CONFIRMED)) {
$this->guard()->logout();
return $this->sendSuspendedResponse($request);
} else {
$this->guard()->login($this->guard()->user());
return $this->sendLoginResponse($request);
}
}
}

Laravel 5 Redirect from a sub-method

I'm using Socialite to get user information from facebook. All is going well but my redirect isn't working
Sub-routes
I read that it's not possible to do a redirect from a submethod, or
any method that's not in your routes.
But how else can i redirect the user after I logged them in?
My URL looks like this after the successfull facebook handshake
http://tmdb.app/auth/login/facebook?code=AQBTKNZIxbfdBruAJBqZ8xx9Qnz...
Code
class SocialController extends Controller {
public function login(Authenticate $authenticate, Request $request)
{
return $authenticate->execute($request->has('code'), $this);
}
public function userHasLoggedIn($data)
{
$user = User::where('provider_id', $data->id)->first();
if( !$user )
{
$user = User::create([
'name' => $data->name,
'email' => $data->email,
'provider' => 'facebook',
'provider_id' => $data->id
]);
}
// NOT WORKING!
return redirect('test');
}
}
Your login function should be handling the redirect.
I'm guessing execute returns $data if the user is sucessfully logged in and false if not.
class SocialController extends Controller {
public function login(Authenticate $authenticate, Request $request)
{
if($data = $authenticate->execute($request->has('code'), $this))
{
$user = User::where('provider_id', $data->id)->first();
// maybe delegate the user creation to another class/service?
if( !$user )
{
$user = User::create([
'name' => $data->name,
'email' => $data->email,
'provider' => 'facebook',
'provider_id' => $data->id
]);
}
return redirect('test');
}
return redirect('fail_view');
}
}
You can do it using PHP header function in Laravel sub method. I try it and works properly. Hope it can help you.
// You can using the following code
$url= url("about-laravel");
header("Location:" . $url);
exit;
// Or using the following code to redirect and keep set flash message
$result= $this->yourMethod(); // return redirect($this->route)->with('flash_message', 'I\'m Flash Message'); for TRUE or NULL for false
if( $result ){
return $result;
}

Categories