My case is that a user's unique email can have many accounts .
Means that one email is associated with many accounts on unique username's.
My current code works for mail, I want to send email on their username, Means that user will enter his username then the email associate with that username will get the password reset link
Current working code for direct email :
public function postEmail(Request $request)
{
$validator = Validator::make(Input::get(),
[
'email' => 'required|email'
]
);
if ($validator->fails()) {
return redirect()
->back()
->withErrors($validator->errors())
->with('message', 'Please fix your form fields.')
->with('form', 'recover')
->withInput(Input::except('password'));
}
$response = $this->passwords->sendResetLink($request->only('email'), function($message)
{
$message->subject('Password Reminder');
});
switch ($response)
{
case PasswordBroker::RESET_LINK_SENT:
return redirect()
->back()
->with('message', 'A verification email was sent to your email inbox.')
->with('form', 'recover')
->withInput(Input::except('password'));
case PasswordBroker::INVALID_USER:
dd('true');
}
}
I have added the following line :
$usernameToEmail = App\User::where('name','=', Input::get());
And then i passed $usernameToEmail->email to
$response = $this->passwords->sendResetLink($usernameToEmail->email,
function($message)
{
$message->subject('Password Reminder');
});
Which throws the following error :
Type error: Argument 1 passed to Illuminate\Auth\Passwords\PasswordBroker::sendResetLink() must be of the type array, string given
This is happening because the PasswordBroker is trying to retrieve a use by the credentials that you give and it will make a DB query to get a user. So if your username is unique you could do it like this:
$this->passwords->sendResetLink(
['username' => $username],
function($message){...}
);
This will not work you need to have unique email and username.
as token is generated against a unique users row in table and used when resetting.
Related
I have a client which want to save his data encrypted in the database (email, name etc.). He wants to log in with the email too. I made the functionality to log in with encrypted email but the problem is that after log in I am redirected to a blank page with the url /login when I should be redirected to /business-accounts. If I delete manually the /login from the url I am redirected to the /business-accounts which I need to be redirected. Before doing the ecrypted email authentication everything worked fine.
AuthenticatedSessionController.php
public function store(LoginRequest $request)
{
//check user is validated
User::all()->filter(function ($user) use ($request) {
if($user->email == $request->email){
if($user && $user->status==0){
throw ValidationException::withMessages([
'validation' => 'Account not verified.'
]);
}
//get user email crypted for login
$request->merge(['email' => User::find($user->id)->get_email_crypted()]);
$request->authenticate();
$request->session()->regenerate();
//set user session
UserService::set_session($user);
return redirect()->intended(RouteServiceProvider::HOME);
}
});
}
I printed a dd() before the return and seems like everything is working fine till there.
LoginRequest.php
public function authenticate()
{
$this->ensureIsNotRateLimited();
if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'email' => __('auth.failed'),
]);
}
RateLimiter::clear($this->throttleKey());
}
RouteServiceProvider.php
public const HOME = '/business-accounts';
Encryption and decryption is made in the User model with get/setEmailAttribute. In the authenticate() method I could see that it is not entering the if where Auth::attempt is located.
I tried to make it work in PasswordResetLinkController too but all I could get is the same blank page with the url /forgot-password and no email received in the inbox.
My Laravel version is 8.x.
L.E. I dumped something before the return redirect() and I saw that in the browser after the login submit I am redirected back to the /login form, so I am thinking that I am getting in a loop or something.
L.E.2.
I somehow resolved this. The thing that I done was changing the crypting method on the email column. I changed the Laravel cripting method with the openssl_crypt function.
User Model
public function setEmailAttribute($value)
{
if (!is_null($value)) {
$this->attributes['email'] = openssl_encrypt($value, "AES-128-ECB", env('EMAIL_ENCRYPT_KEY', false));
}
}
Where the crypting key is located in .env.
AuthenticatedSessionController.php
public function store(LoginRequest $request)
{
//check user is validated
$user = User::where('email', openssl_encrypt($request->email, "AES-128-ECB", env('EMAIL_ENCRYPT_KEY', false)))->first();
if($user && $user->status==0){
throw ValidationException::withMessages([
'validation' => 'Contul nu este verificat'
]);
}
//set email from request to encrypted email
$request->merge(['email' => User::find($user->id)->get_email_crypted()]);
$request->authenticate();
$request->session()->regenerate();
UserService::set_session($user);
return redirect()->intended(RouteServiceProvider::HOME);
}
you can take a look in the log file in /storage/logs/laravel.log for the error message
also, you could change the .env file to show_errors = true and it will show the error in the browser
Use return redirect()->route('your-route-name'); maybe can help you.
Working in Laravel Spark and have a custom API endpoint that checks a user credentials but doesn't log them in, just returns the user data.
I have a form request that checks the email and password for being required and then I use
withValidator()
to run some more validation on the password.
public function rules()
{
return [
'email' => 'required|email|exists:users',
'password' => 'required'
];
}
public function withValidator($validator)
{
$validator->after(function ($validator) {
$user = User::where('email', $this->email)->first();
if ( $user && !Hash::check($this->password, $user->password) ) {
$validator->errors()->add('password', 'Incorrect password');
} else {
// Pass the user to the controller
}
});
}
In my controller I want to be able to return the user, but I dont want to run through the process of checking the hash etc.
I would simply like to be able to do:
return $request->user
Or similar.
Is there a way to do this?
Why not just do this in the controller?
$user = User::where('email', $request->email)->first();
If you put this after the validator, you already know the user is valid, otherwise the validator would fail before it got to that point.
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');
}
I am trying to configure a laravel 5 app that will login users based on their username with password, if the username and password method fails the app will try to check the other table if the data in the username variable is available in my case their employee_id. So here is my code for logging users in with the conventional laravel method:
$authdetails = array(
'email' => $request->input('email'),
'password' => $request->input('password')
);
if (Auth::attempt($authdetails)) {
// Authentication passed...
return redirect()->to('/home');
}
else {
return back()->with('error', 'Invalid username or password')->withInput();
}
}
I have two tables inside the database. (1)users, (2)userdetails, the user table contains your standard laravel users default migration table, the userdetails table contains the details for the user. The first method of the login authentication uses the users table, the second method of login I want to implement if the first fails uses the userdetails table.
What I'm trying to do is if the first method of the login fails, it will search the other table for a value of the variable passed if there is then it will authenticate it.
If you have the employee_id column in your users table, then it's really easy. You just try to authenticate with both sets of credentials.
public function postLogin(Request $request) {
$this->validate($request, [
'usernameOrEmployeeId' => 'required',
'password' => 'required',
]);
// Attempt login via username
$credentials = [
'username' => $request->input('usernameOrEmployeeId'),
'password' => $request->input('password'),
];
if (Auth::attempt($credentials, $request->has('remember'))) {
return redirect()->intended($this->redirectPath());
}
// Swap username and employee_id
$credentials['employee_id'] = $request->input('usernameOrEmployeeId');
unset($credentials['username']);
// Attempt login via employee_id
if (Auth::attempt($credentials, $request->has('remember'))) {
return redirect()->intended($this->redirectPath());
}
// Login attempts failed
return redirect($this->loginPath())
->withInput($request->only('usernameOrEmployeeId', 'remember'))
->withErrors([
'usernameOrEmployeeId' => $this->getFailedLoginMessage(),
]);
}
If you don't have an employee_id column in your users table, then it's a bit more difficult. You would use the same code as above, except you would replace this part:
// Swap username and employee_id
$credentials['employee_id'] = $credentials['username'];
unset($credentials['username']);
with something like this:
// Find user_id by looking up the employee relationship
$employee = App\Employee::findOrFail($request->input('usernameOrEmployeeId'));
$credentials['id'] = $employee->user->id;
unset($credentials['username']);
Don't forget the unset(). It is important because if you leave username in the array, Laravel will try to authenticate with all 3 pieces of info and will always fail because we already know the username/password don't match.
Also, you don't have to use any third party libraries. This is a simple problem with a relatively simple solution.
If you want to login with two different table when first one is failed to authenticate.You have to use multiauth library Here and Here.
and then use like this.
$authdetails = array(
'email' => $request->input('email'),
'password' => $request->input('password')
);
if (Auth::user1()->attempt($authdetails)) {
// Authentication passed...
return redirect()->to('/home1');
}
if (Auth::user2()->attempt($authdetails)) {
// Authentication passed...
return redirect()->to('/home2');
}
else {
return back()->with('error', 'Invalid username or password')->withInput();
}
}
How to authenticate a user password from a given request in Laravel? How is the password checked against the password hash stored in the database?
First, you'll need to find the User who is logging in based on email address or username or however you identify them, for example:
$user = User::where('email', '=', 'email#address.com')->first();
Then, you'll need to CHECK the hashed password, like so:
Hash::check('INPUT PASSWORD', $user->password);
This will return true or false based on whether or not the password matches.
Laravel Login Authentication:
public function login(Request $request)
{
$email = $request->input('email');
$password = $request->input('password');
$user = User::where('email', '=', $email)->first();
if (!$user) {
return response()->json(['success'=>false, 'message' => 'Login Fail, please check email id']);
}
if (!Hash::check($password, $user->password)) {
return response()->json(['success'=>false, 'message' => 'Login Fail, pls check password']);
}
return response()->json(['success'=>true,'message'=>'success', 'data' => $user])
}
Step 1: first get user data from DB
$user = User::where('email', '=', $request->input('email'))->first();
Step 2: Get user password as
$user->password
Step 3: Validate it as
if(Hash::check($password, $user->password)) {
return response()->json(['status'=>'true','message'=>'Email is correct']);
} else {
return response()->json(['status'=>'false', 'message'=>'password is wrong']);
}
woo hoo!!!!! you have done :)
$email = Input::get('email');
$user = User::where('email', '=', $email)->first();
if (!$user) {
return response()->json(['success'=>false, 'message' => 'Not Login successfull']);
}
if (!Hash::check(Input::get('password'), $user->password)) {
return response()->json(['success'=>false, 'message' => 'Not Login successfull']);
}
return response()->json(['success'=>true,'message'=>'success', 'data' => $user]);
From Laravel 5 onward, you can use the bcrypt() function to hash a plaintext. So, you can save that hashed password in DB and then, compare the hashed password again to match.
$save_password = bcrypt('plain_text_password');
$check_password = bcrypt('provided_password_while_login_request');
And then, compare these two. You're good to go.
Or, if you want to go with the Laravel way:
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
// Authentication passed...
return redirect()->intended('dashboard');
}
As per Laravel documentation, and I quote: "The attempt method accepts an array of key / value pairs as its first argument. The values in the array will be used to find the user in your database table. So, in the example above, the user will be retrieved by the value of the email column. If the user is found, the hashed password stored in the database will be compared with the password value passed to the method via the array. You should not hash the password specified as the password value, since the framework will automatically hash the value before comparing it to the hashed password in the database. If the two hashed passwords match an authenticated session will be started for the user.
The attempt method will return true if authentication was successful. Otherwise, false will be returned."
You can create the below method to find the user authentication as explained on the laravel website for authentication:
public function authenticate(Request $request)
{
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
// Authentication passed...
// use the below code to redirect the user to dashboard.
// return redirect()->intended('dashboard');
}
}
Please check the link below for more details regarding authentication on laravel website:
https://laravel.com/docs/5.6/authentication#authenticating-users