Laravel sessions table user_id always null - php

I tried to set the session but the user_id column is always null. Other columns are working just fine. Is user_id reserved for anything? Did this happen to anyone?
What I am trying here is to authenticate the user,save the data to session and redirect to dashboard.
Here is the code:
public function login(Request $request)
{
$validator = validator::make($request->all(),[
'username' => 'required',
'password' => 'required'
]);
if($validator->fails()){
return redirect('/')
->withInput()
->withErrors($validator);
}
$username = $request->get('username');
$user = User::where('username', $username)->first();
$checkpass = false;
if(!empty($user)){
$password = $request->get('password');
$dbpass = $user->getAttributes()['pass'];
$checkpass = Hash::check($password, $dbpass);
if($checkpass){
//saving session after success login check
$request->session()->put('id',\Session::getId());
$request->session()->put('user_id', $user->id);
$request->session()->put('ip_address', $request->ip());
$request->session()->put('user_agent', $request->header('User-Agent'));
$request->session()->put('payload', base64_encode($request->getContent()));
$request->session()->put('last_activity', time());
//redirect to dashboard
return redirect('/dashboard');
}
}
if(empty($user) || $checkpass == false){
$errors = new MessageBag(['password'=>['Email and/or password invalid.']]);
return redirect('/')
->withErrors($errors)
->withInput(Input::except('password'));
}
}

You are using the database session driver. Laravel will thus handle sessions via the Illuminate\Session\DatabaseSessionHandler.php. If you check out the source, you will find a method getDefaultPayload which is called whenever you write/save the session to the database.
Inside this method you will find this:
if ($container->bound(Guard::class)) {
$payload['user_id'] = $container->make(Guard::class)->id();
}
which sets the user_id to the currently logged in user via Laravel's Guard. However, since you are not logging in with the Guard, this method will see the current user id as null and that is why you always get null.
Furthermore, in truth none of the properties you are setting are actually being set. Instead, they are all being set in the getDefaultPayload method of DatabaseSessionHandler.php.
This is where you should start in figuring out the best way to integrate Laravel's database session with your implementation. As I don't have more information about your application, I can't give you further direction as what the best solution might be and what would be the best change to make. Without knowing anything though, I might look into integrating your login system with the Laravel Guard because it does provide some other functionality as well. Or, a quicker solution might be to just directly modify this bit of the getDefaultPayload method.

You can do this under Illuminate\Session\DatabaseSessionHandler.php
protected function performUpdate($sessionId, $payload)
{
if(!Auth::check())
{
unset($payload['user_id']);
}
return $this->getQuery()->where('id', $sessionId)->update($payload);
}

It will fix if you using Auth::attempt because when you attempt the Auth facade laravel will set the user_id on the Session table/file/etc, something like this:
if(Auth::attempt([
'email' => $email,
'password' => $password
])) {
$user = Auth::user();
return [
'user' => $user,
];
}

Try this solution by making some changes Illuminate\Session\DatabaseSessionHandler.php
/**
* Add the user information to the session payload.
*
* #param array $payload
* #return $this
*/
protected function addUserInformation(&$payload)
{
if ($this->container->bound(Guard::class)) {
$payload['user_id'] = $this->userId();
}
// UPDATE "user_id" IN TABLE "sessions" USING YOUR OWN SESSION DATA [BEGIN]
if(\Session::has('login_id')){
$my_user = \Session::get('login_id');
$payload['user_id'] = $my_user;
}
// UPDATE "user_id" IN TABLE "sessions" USING YOUR OWN SESSION DATA [END]
return $this;
}
But make sure the logged-in session has been created by your own auth function first.
Sample dd(Session::all); of my application:
array:8 [
"_token" => "VSI617e5HjtrYnj59hGPG9AS0R7y5vvUA1fQ7mV6"
"language" => "EN"
"_previous" => array:1 []
"_flash" => array:2 []
"login_id" => "123"
]

Related

How to manually (formless) Authenticate user? Cakephp 4x

User doesn't stay logged in when I use setIdentity.
$user = $this->Users->get(1);
$this->Authentication->setIdentity($user);
$userInfo = $this->Authentication->getIdentity(); // Returns good.
$this->redirect('Somewhere');
Somewhere:
$userInfo = $this->Authentication->getIdentity(); // Returns null.
I am not using form. There is no POST happening only dynamically setting user based on some algo...
Application.php
public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
{
$service = new AuthenticationService([
'unauthenticatedRedirect' => '/login',
'queryParam' => 'redirect',
]);
/* $fields = [
'username' => 'username',
'password' => 'password'
];
$service->loadIdentifier('Authentication.Password', compact('fields')); */
// Load the authenticators, you want session first
$service->loadAuthenticator('Authentication.Session');
return $service;
}
You are setting the principal information on the Authentication but you loose it on the next request because it's not persisted (I'm sparing you the "http is stateless" song...)
Part of your setIdentity should also be persisting the identity. This can be achieved in different ways:
in the session, when using sessions
in a JWT token, when using tokens
Here is how AuthenticationService does it in persistIdentity. I suggest you also have a look at the JWT auth configuration.

how to create custom registration in Laravel with two tables?

My registration form additionally accepts the name of the user's company, which I want to insert in a separate table "Holdings". All data is successfully saved to the Holdings and Users table, but an error occurs at the last step when redirecting to the home page.
ResgisterController:
protected function create(array $data)
{
//Mail::to($data['email'])->send(new Welcome($data['name']));
$id = User::insertGetId([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
'role' => 8
]);
$oHolding = new Holdings;
$oHolding->shortname = $data['orgname'];
$oHolding->creator = $id;
$oHolding->save();
DB::table('users')->where('id', $id)->update([
'holding_id' => $oHolding->id,
]);
$user = DB::table('users')->select('*')->where('id', $id)->get();
return $user;
}
Error Message:
Argument 1 passed to Illuminate\Auth\SessionGuard::login() must implement interface Illuminate\Contracts\Auth\Authenticatable, instance of Illuminate\Support\Collection given, called in /Users/admin/Sites/jetime/vendor/laravel/framework/src/Illuminate/Foundation/Auth/RegistersUsers.php on line 35
Login Function
public function login(AuthenticatableContract $user, $remember = false)
{
$this->updateSession($user->getAuthIdentifier());
// If the user should be permanently "remembered" by the application we will
// queue a permanent cookie that contains the encrypted copy of the user
// identifier. We will then decrypt this later to retrieve the users.
if ($remember) {
$this->ensureRememberTokenIsSet($user);
$this->queueRecallerCookie($user);
}
// If we have an event dispatcher instance set we will fire an event so that
// any listeners will hook into the authentication events and run actions
// based on the login and logout events fired from the guard instances.
$this->fireLoginEvent($user, $remember);
$this->setUser($user);
}
I will be glad of any help, how to fix the error?
You are returning a collection rather than an instance of a class that implements Authenticatable.
You can see this happening here:
$user = DB::table('users')->select('*')->where('id', $id)->get();
return $user;
If you have the User model that ships with Laravel, then you'll actually want to do:
$user = User::find($id);
return $user;
Although your whole create method could be cleaned up to streamline all of this, however that isn't the topic of your question.

Laravel Socialite log out and database storing

I am trying to set up Socialite in Laravel for facebook logging. I got user logged in , but now I have a problem storing the details in the database.
Also I would like to know how to notice my app that User is logged in? For normal loggin I used native AuthController and everything goes smooth.
Now if user try to log in again, then Laravel automatically redirect it to the url without logging, with appended code like this ?code=AQBCM-KbFqB-VJepSJ-45nFURnsvPPdpdqOu...
So how can I logout the user completely and how can I store the details for the next logging??
This is what I am using but it is not working:
public function getSocialAuth($provider=null)
{
if(!config("services.$provider")) abort('404'); //just to handle providers that doesn't exist
return $this->socialite->with($provider)->redirect();
}
public function getSocialAuthCallback($provider=null)
{
if($user = $this->socialite->with($provider)->user()){
dd($user);
/* This is also not working:
$user1 = new User;
$user1->facebook_id = $user->getId();
$user1->email=$user->email();
$user1->fullname=$user->name();
$user1->provider="facebook";
$user1->save();*/
// not working:
User::create([
'facebook_id' => $user->getId(), 'email' => $user->email(),
'fullname' => $user->name()
]);
}else{
return 'something went wrong';
}
}

Login functionality in laravel 4.2 based on database records

I am fairly new to laravel and I am trying to create a login functionality in laravel 4.2 where the username and password is fetched from the database. I am planning to use this code in the controller but i don't know how to tweak it in such a way that the username and password should be based from a database record
public function postLogin()
{
$credentials = [
'username'=>Input::get('username'),
'password'=>Input::get('password')
];
$rules = [
'username' => 'required',
'password'=>'required'
];
//validating the credentials.
$validator = Validator::make($credentials,$rules);
//in case the credentials are valid. Try to login the user.
if($validator->passes())
{
if(Auth::attempt($credentials))
{
//if successfull redirect the user
return Redirect::to('user/home');
}
//else send back the login failure message.
return Redirect::back()->withInput()->with('failure','username or password is invalid!');
}
//send back the validation errors.
return Redirect::back()->withErrors($validator)->withInput();
}
public function getLogout()
{
Auth::logout();
return Redirect::to('/');
}
Any ideas? Thanks for any help in advance.
You don't need to tweak that code. Default behavior of Auth is to use the eloquent driver which uses the database you configured with your app.
So Auth::attempt($credentials) will use the database table associated (default users table) to authenticate the user with the provided credentials.
You can change the model or table name like opitons in Auth.php file in config directory.
Edit
To validate and login a user manually use the following.
public function postLogin()
{
$credentials = Input::only('username', 'password');
$validator = Validator::make($credentials, [
'username' => 'required',
'password'=>'required'
]);
if($validator->fails())
{
return Redirect::back()->withErrors($validator)->withInput();
}
$user = User::where('SystemUserName', $credentials['username'])->first();
if (! $user || ! Hash::check($credentials['password'], $user->SystemUserPassword)) {
return Redirect::back()->withInput()->with('failure','username or password is invalid!');
}
Auth::login($user);
return Redirect::to('user/home');
}

Laravel 4 create an user programatically with Zizaco/confide

I'm trying to create a user with the Zizaco/confide library, the user data comes from Facebook and not from a form.
I try this :
$user_profile = Facebook::api('/me','GET');
$new_user = new User;
$new_user->username = $user_profile['name'];
$new_user->password = Hash::make('secret');
$new_user->email = $user_profile['email'];
$new_user->confirmation_code = '456456';
$new_user->confirmed = true;
$new_user->save();
but it doesn't save the user. Any help ?
I found the problem, the confide library sets some default rules to create the user, you need to pass this rules to save a user:
public static $rules = array(
'username' => 'required|alpha_dash|unique:users',
'email' => 'required|email|unique:users',
'password' => 'required|between:4,11|confirmed',
'password_confirmation' => 'between:4,11',
);
with this example it works:
$user = new User();
$user->username = 'asdasd';
$user->email = 'angorusadf#gmail.com';
$user->password = '12312312';
$user->password_confirmation = '12312312';
$user->save();
Mabe the method should give you some information when you don't pass the rules.
Maybe it's a pretty late answer, but I'm posting this for future reference because I was myself looking for an answer to the same question, How to create a user programatically in zizaco/confide? or more generally, how to bypass zizaco/confide's requirement for setting a password when saving a user for the first time?
well, the answer is pretty simple, thanks to the new architecture which Zizaco implemented in the 4.* branch, it's now possible to register a new user validator class see more at the package's readme in short all you need in this very case though, is just to extend the current User validator and override validatePassword() to make it accept empty passwords for new users.
Below is an example implementation:
In routes.php
// we need to register our validator so that it gets used instead of the default one
// Register custom Validator for ConfideUsers
App::bind('confide.user_validator', 'MyUserValidator');
In app/models/MyUserValidator.php (that's basically a copy of the function in the class, simply just added a check whether this is a old user or not (if the user has an ID then this is an update operation) if this is a new user, the method always returns true!
/**
* Class MyUserValidator
* Custom Validation for Confide User
*/
class MyUserValidator extends \Zizaco\Confide\UserValidator //implements \Zizaco\Confide\UserValidatorInterface
{
/**
* Validates the password and password_confirmation of the given
* user
* #param ConfideUserInterface $user
* #return boolean True if password is valid
*/
public function validatePassword(\Zizaco\Confide\ConfideUserInterface $user)
{
$hash = App::make('hash');
if($user->getOriginal('password') != $user->password && $user->getOriginal('id')) {
if ($user->password == $user->password_confirmation) {
// Hashes password and unset password_confirmation field
$user->password = $hash->make($user->password);
unset($user->password_confirmation);
return true;
} else {
$this->attachErrorMsg(
$user,
'validation.confirmed::confide.alerts.wrong_confirmation',
'password_confirmation'
);
return false;
}
}
unset($user->password_confirmation);
return true;
}
}

Categories