Laravel\Socialite\Two\InvalidStateException - laravel

Hi i am using laravel socialite for social logins with facebook and google and it absoultely working fine on my local server but when i deploy this on my web hosting it gives me error
Laravel\Socialite\Two\InvalidStateException
it is only for when i try to login with google in my app but it is working fine for facebook i tried many solutions as add stateless() in both google redirect method and callback method and single single too but all in vain i also tried to change in config/session where domain shows as null to my site name but again got same issue here is my code for google redirect and callback
public function redirectToGoogle()
{
return Socialite::driver('google')->redirect();
}
public function handleGoogleCallback()
{
$user = Socialite::driver('google')->user();
$this->_registerOrLoginUser($user);
return redirect()->route('home');
}
protected function _registerOrLoginUser($data)
{
$user = User::where('email','=',$data->email)->first();
if(!$user){
$user = new User();
$user->first_name = $data->name;
$user->email = $data->email;
// $user->provider_id = $data->provider_id;
$user->avatar = $data->avatar;
$user->save();
}
Auth::login($user);
}
please let me know if i'm missing something or doing wrong i'll appreciate your response in advance thank you

Related

Laravel socialite, redirect back to page where button was clicked

I have a laravel website where certain news articles are 'gated' meaning they have to login/signup in order to read more than the first paragraph.
I have Laravel Socialite installed, so that users can login with Google. What I would like is for users to login via google, then be redirected back to the page which they were viewing before they clicked the 'Login using google' button.
I'll obviously hide the login area when the user is logged in.
Is this possible?
This is my code, however the redirect()->intended() does not work:
public function redirectToProvider()
{
return Socialite::driver('google')->redirect();
}
public function handleProviderCallback()
{
try {
$user = Socialite::driver('google')->user();
} catch (\Exception $e) {
return redirect('/login');
}
// check if they're an existing user
$existingUser = User::where('email', $user->email)->first();
if($existingUser){
// log them in
auth()->login($existingUser, true);
} else {
// create a new user
$newUser = new User;
$newUser->name = $user->email;
$newUser->email = $user->email;
$newUser->roles_id = 1;
$newUser->save();
auth()->login($newUser, true);
}
return redirect()->intended();
}
Thanks in advance.
M
Save the url in a session and retrieve it in the redirect method of the controller.

Laravel SAML - user automatically logged out after log in

I have connected my Laravel app to the Azure, and I'm using the SAML2 protocol for user authentication. The issue which i have is that user is logged in application (Auth::login($user)), and after that when printing auth()->user() i get logged in user object. However, somehow user session is destroyed after that, and the user is redirected to the login page. Callback for SAML response is located in a service provider boot() method and looks like this:
public function boot()
{
Event::listen('Aacotroneo\Saml2\Events\Saml2LoginEvent', function (Saml2LoginEvent $event) {
$messageId = $event->getSaml2Auth()->getLastMessageId();
// Add your own code preventing reuse of a $messageId to stop replay attacks
$user = $event->getSaml2User();
$userMap = config('saml2_settings.user_map');
$emailAddress = $user->getAttribute($userMap['email']);
$laravelUser = User::where('email', '=', $emailAddress[0])->first();
if ($laravelUser) {
Auth::login($laravelUser);
return;
}
$azureService = new AzureService();
$newUser = $azureService->createNewUserFromSaml($userMap, $user);
if ($newUser){
Auth::login($newUser);
}
});
}

ADLDAP openLDAP authentication - Session not stored - returning to login page

My environment is a laravel 5.8 with adldap2 in version 6.0.8 web app and an openLDAP directory.
After hours, I finally could authenticate my user against the openLDAP directory and also the database import into the users table works:
Id name username password remember_token created_at updated_at
King king $2y$10$YF9q7cYqjYnkl.We4Evwv.u/a2sddrfBA3pohgpS2vR... j4AOUHSlkHE3IQW7bsgF7pOIY8EAss6iukfnKhwi2lqXR0eTjE... NULL NULL
When I check the variable user in the function: attemptLogin -> $this->guard()->login($user, true); it is from the DB and seems to be fine. But still after I log in, I also get the message "Redirecting to http://localhost/home.", it returns to the login page and is still not logged in.
For LDAP authentication I followed mostly this example: https://jotaelesalinas.github.io/laravel-simple-ldap-auth/ even if it is a bit obsolete.
My attemptLogin function looks like this:
protected function attemptLogin(Request $request)
{
$username = Adldap::search()->users()->select('mail','uid','displayName')->findBy('cn', request()->get('username'));
$result = 1;
if($username){
if(Adldap::auth()->attempt($username->getdistinguishedName(), request()->get('password'))){
echo("success");
// Check group
$group = Adldap::search()->groups()->findOrFail('cio');
foreach ($group->getMemberNames() as $name) {
if($name === $username->getAccountName()){
echo("The user is a member of the group.");
$result = 0;
}
}
if ($result != 0){
$result = 2;
}
} else {
echo("Password wrong");
$result = 1;
}
} else {
echo(request()->get('username') . " not found");
$result = 1;
}
if($result == 0) {
// the user exists in the LDAP server, with the provided password
echo("Everything ok");
$user = \App\User::where($this->username(), $username->getAccountName())->first();
if (!$user) {
// the user doesn't exist in the local database, so we have to create one
$user = new \App\User();
$user->username = $username;
$user->password = '';
// you can skip this if there are no extra attributes to read from the LDAP server
// or you can move it below this if(!$user) block if you want to keep the user always
// in sync with the LDAP server
//dd($username->getDisplayName());
$sync_attrs = $this->retrieveSyncAttributes($username->getAccountName());
//dd($sync_attrs);
foreach ($sync_attrs as $field => $value) {
$user->$field = $value !== null ? $value : '';
}
}
$this->guard()->login($user, true);
return 0;
}
// the user doesn't exist in the LDAP server or the password is wrong
// log error
return $result;
}
Web.php
Route::get('login', 'Auth\LoginController#showLoginForm')->name('login');
Route::post('login', 'Auth\LoginController#login');
Route::post('logout', 'Auth\LoginController#logout')->name('logout');
Route::get('/home', 'HomeController#index')->name('home');
Has anyone an idea what I am missing? Or if you need more information, please tell me. It seems like the session is not stored.
Thanks in advance
Stephan
A small update after playing around some more hours. It seems like that Auth is after the successful login null. So tried different approaches I could find on the internet like changing the web.php routes or adding the protected $user variable to the LoginController.php but of course without any success.
I figured out that when I change the middleware from auth to web, I will get a session but the Auth::User() is still empty
Route::group(['middleware' => 'auth'], function () {
Route::get('/home', 'HomeController#index')->name('home');
});
After spending more and more hours, I finally found the solution in this thread: Laravel Auth:attempt() will not persist login
My issue was that I was using "echo's".
It cost me probably some days of my life

Dynamic social app credentials in socialite package in Laravel

I'm trying to build a multi tenant app, where I have configured the database, the views folder, I know there must be some way out to configure the credentials of social app login for socialite. Well I tried few things to set it dynamically.
STEP 1
I created a class with the name of socialite in a separate folder and when the social login is called I'm implementing the following in my controller:
public function redirectSocialLogin()
{
$social = new SocialiteProvider();
$fb = $social->makeFacebookDriver();
return $fb->redirect();
}
and while callback I used following:
public function callbackSocialLogin($media)
{
$user = Socialite::driver($media)->user();
$data['name'] = $user->getName();
$data['email'] = $user->getEmail();
dd($data);
}
In my class I've following codes:
public function makeFacebookDriver()
{
$config['client_id'] = 'XXXXXXXXXXXXXXX';
$config['client_secret'] = 'XXXXXXXXXXXXXXX';
$config['redirect'] = 'http://XXXXXXXXXXXX/auth/facebook/callback';
return Socialite::buildProvider('\Laravel\Socialite\Two\FacebookProvider', $config);
}
It redirects perfectly to the social page but while getting a callback I'm getting an error, It again fetches the services.php file for configuration and doesn't get any.
STEP 2
I made a ServiceProvider under the name of SocialiteServiceProvider and extended the core SocialiteServiceProvider and placed the following codes:
protected function createFacebookDriver()
{
$config['client_id'] = 'XXXXXXXXXXXXXXX';
$config['client_secret'] = 'XXXXXXXXXXXXXXXXXXXX';
$config['redirect'] = 'http://XXXXXXXXXXX/auth/facebook/callback';
return $this->buildProvider(
'Laravel\Socialite\Two\FacebookProvider', $config
);
}
But again it throws back error which says driver is not setup. Help me out in this.
Thanks.
In your STEP 1, update the callback as below mentioned & try. $media is actually Request. So when initialising Socialite::driver($media) you are actually passing Request where you have to pass Facebook.
public function callbackSocialLogin(Request $request) {
$fbDriver = (new SocialiteProvider())->makeFacebookDriver();
$user = $fbDriver->user();
$data['name'] = $user->getName();
$data['email'] = $user->getEmail();
...
}

Attach authenticated user to create

I'm trying to attach the currently logged in user to this request, so that I can save it in the database. Can someone point me in the right direction, please?
public function store(CreateLeadStatusRequest $request)
{
$input = $request->all();
$leadStatus = $this->leadStatusRepository->create($input);
Flash::success('Lead Status saved successfully.');
return redirect(route('lead-statuses.index'));
}
So, I have come up with the following using array_merge, but there must be a better way, surely?
public function store(CreateLeadStatusRequest $request)
{
$input = $request->all();
$userDetails = array('created_by' => Auth::user()->id, 'modified_by' => Auth::user()->id);
$merged_array = array_merge($input, $userDetails);
$leadStatus = $this->leadStatusRepository->create($merged_array);
Flash::success('Lead Status saved successfully.');
return redirect(route('lead-statuses.index'));
}
So you can use Auth Facade to get information of currently logged user.
For Laravel 5 - 5.1
\Auth::user() \\It will give you nice json of current authenticated user
For Laravel 5.2 to latest
\Auth::guard('guard_name')->user() \\Result is same
In laravel 5.2, there is new feature called Multi-Authentication which can help you to use multiple tables for multiple authentication out of the box that is why the guard('guard_name') function is use to get authenticated user.
This is the best approach to handle these type of scenario instead of attaching or joining.
public function store(CreateLeadStatusRequest $request)
{
$input = $request->all();
$userDetails = \Auth::user(); //Or \Auth::guard('guard_name')->user()
$leadStatus = $this->leadStatusRepository->create($input);
Flash::success('Lead Status saved successfully.');
return redirect(route('lead-statuses.index'));
}
Hope this helps.

Resources