I am building a testing routine in Laravel 5.1 to run through the login process I have just created. I am wanting, as part of the testing, to test the password reset and change process.
The issue is that the password reset process generates and row in a table with a timestamp and uuid. The link remains valid for 1 hour for the reset to work.
The flow is:
1- Reset password by entering email address
2- System generates email with uuid link and sends to the user (currently it appears in the Laravel log).
3- User clicks on link from email, and if within one hour since it was generated, the user is presented with a password change screen. The link is also deleted from the table.
So now for my test code:
public function testSendPasswordLink()
{
$this->visit('/login')
->click('Forgot Your Password?')
->seePageIs('/forgot-password')
->type('test#test.com','email')
->press('Send Password Reset Link')
->seePageIs('/login')
->see('A password reset link was sent to the email address supplied.')
->seeInDatabase('password_resets', ['email' => 'test#test.com']);
}
I would like to:
->getFromDatabase('password_resets', 'uuid')
->visit('/reset-password/'.$uuid)
->see(....
Is there a way of doing the above? I know how to see in the table but not how to get from the table in the test.
Alternatively is there a way to accomplish this via a different set of steps?
Thanks!
Wow, insanity setting in... well, I am new at this so I will not execute myself as yet...! The answer was rather obvious (after sleeping on it!)
All I had to do is query the table and retrieve the token to perform the password reset test... below is the finished code:
Add Eloquent to the test php file
use Illuminate\Database\Eloquent\Model;
Below is the complete function:
public function testChangePassword()
$this->visit('/login')
->click('Forgot Your Password?')
->seePageIs('/forgot-password')
->type('test#test.com','email')
->press('Send Password Reset Link')
->seePageIs('/login')
->see('A password reset link was sent to the email address supplied.')
->seeInDatabase('password_resets', ['email' => 'test#test.com']);
$uuid = DB::table('password_resets')
->where('email', '=', 'test#test.com')
->value('token');
$this->visit('/reset-password/' . $uuid)
->type('bbbbbbbb','password')
->type('bbbbbbbb','password_confirmation')
->press('Change Password')
->see('Your password was reset.')
->seePageIs('/login')
->type('test#test.com','email')
->type('bbbbbbbb','password')
->press('Sign In')
->seePageIs('/welcome')
->click('Logout')
->seePageIs('/login');
// Change password back
$this->visit('/login')
->click('Forgot Your Password?')
->seePageIs('/forgot-password')
->type('test#test.com','email')
->press('Send Password Reset Link')
->seePageIs('/login')
->see('A password reset link was sent to the email address supplied.')
->seeInDatabase('password_resets', ['email' => 'test#test.com']);
$uuid = DB::table('password_resets')
->where('email', '=', 'test#test.com')
->value('token');
$this->visit('/reset-password/' . $uuid)
->type('abcd1234','password')
->type('abcd1234','password_confirmation')
->press('Change Password')
->see('Your password was reset.')
->seePageIs('/login')
->type('test#test.com','email')
->type('abcd1234','password')
->press('Sign In')
->seePageIs('/welcome')
->click('Logout')
->seePageIs('/login');
By the way, I cannot seem to format the code with the {} brackets, so apologies.
Related
I created a user with encrypted password.(bcrypt(password))
In rest api I am getting md5(password) [from app]
How to validate both the password?
\Hash::check($request->password, $user->password)
NOT WORKING
There is no direct way to compare the actual password in Laravel. Laravel never store your password as plain text but a hashed version + salt, so you can check the plain version of the password against the hashed stored version using the Hash::check method:
// original password
$password = 'my-password';
// hashed password
$hashed_password = bcrypt($password);
// something like: "$2y$10$XFs6ocWUaiiB99QvLwTuhOuABIq71D13LmpFdeISh7RsC.SsAthHG";
The hashed version is the one stored.
If you want to check if the validation of a password:
use Illuminate\Support\Facades\Hash;
// ...
$passed = Hash::check($password , $hashed_password); // true
You can not compare passwords encrypted by different ways. You need the plain password. I guess you are trying to make a seamless access for users in your platform in order to avoid the user do two times login (in your system and the api provider system) Am I correct?
In that case, probably you need to think in other way to approach it.
In Laravel 9 i make like this,
first import
use Illuminate\Support\Facades\Hash;
in rules() function
return [
'password' => ['required', function ($attr, $value, $fail) {
$user = User::where('email', $this->request->get('email'))->first();
if ($user && !(Hash::check($value, $user->password))) {
$fail('The ' . $attr . ' is invalid.');
}
}],
];
how to validate email exists in database using luman while create new user?.
my registration controller code
$borrower = borrowerRegistration::create($request->all());
$last_borrower_id=DB::getPdo()->lastInsertId();
$store_borrower_array=array();
$store_borrower_array["borrower_id"]=$last_borrower_id;
$borrower_result = array('status' => 'true','message' =>'The First step borrower registration successfully.','content'=>array('registration'=>$store_borrower_array));
return json_encode($borrower_result);
please give a valuable suggestions.
You can try this way. here User is your Model (I am assuming)
if (User::where('email', '=', Input::get('email'))->exists()) {
// user found
}
Replace Input::get('email') to your email address from where you are getting and storing it.
I am building a webapp that is supposed to be hosted in my company servers and used through the intranet. The requirements are:
The user accesses the webapp.
The app requests an e-mail address.
An e-mail containing a unique link (token) is sent to the address.
The user clicks on the link to log in without a password.
I am developing the webapp using Symfony3 and I thought of using the FriendsOfSymfony User bundle. How can I acheive that? FOSUserBundle is not mandatory.
The login functionalities you want to achieve do not diver that much from e.g. resetting a password by email. Except the temporary token in your use case is used to authenticate the user instead of authenticating a password reset.
A very simple explanation
You should create an entity that stores the authentication token, e.g. AutoLogin that has user, token and a timestamp property.
On the submit of your 'authentication form' a new AutoLogin record gets stored with a relationship towards the user and the user gets notified by email.
Whenever the user clicks the link you should have a method that validates the timestamp for a timeframe and authenticate the user by your user provider.
Examples
Symfony 2: AutoLogin
I think after you accepted the email this is what you can do:
sent url to email like this
<?php
$url = "http://example.com/login.php?token=$token";
?>
Then you login page
<?php
// retrieve token
if (isset($_GET["token"]) && preg_match('/^[0-9A-F]{40}$/i', $_GET["token"]))
{
$token = $_GET["token"];
}
else {
throw new Exception("Valid token not provided.");
}
// verify token
$query = $db->prepare("SELECT username, tstamp FROM pending_users WHERE token = ?");
$query->execute(array($token));
$row = $query->fetch(PDO::FETCH_ASSOC);
$query->closeCursor();
if ($row) {
extract($row);
}
else {
throw new Exception("Valid token not provided.");
}
// do action here, like activating a user account/redirect
// ...
// delete token so it can't be used again
$query = $db->prepare(
"DELETE FROM pending_users WHERE username = ? AND token = ? AND tstamp = ?",
);
$query->execute(
array(
$username,
$token,
$tstamp
)
);
Assuming you have tables like the ones in my queries. Hope i answered you well
There is a service called fos_user.security.login_manager that can help:
public function loginByTokenAction($token)
{
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('AppBundle:User')->findOneByToken($token);
$this->container->get('fos_user.security.login_manager')->loginUser('firewall_name', $user);
// ...
}
source : https://github.com/symfony/symfony/pull/13062
I'm trying to make my first Moodle auth extension where I want to confirm and login users directly after signup.
I've changed the user_signup function in the "email" auth plugin like this:
\core\event\user_created::create_from_userid($user->id)->trigger();
$DB->set_field("user", "confirmed", 1, array("id"=>$user->id));
$user = get_complete_user_data('username', $username);
$DB->set_field("user", "firstaccess", time(), array("id"=>$user->id));
$DB->set_field("user", "lastlogin", 0, array("id"=>$user->id));
update_user_login_times($user);
complete_user_login($user);
redirect("$CFG->wwwroot/enrol/index.php?id=2");
It works so far as the user gets signed up and confirmed. But as for the login I get the following error:
core\session\manager::login_user() must be an instance of stdClass, boolean given
I might be acting stupid here, but I don't know how I could login the new user here. Any help would be very much apprechiated. Thanks!
After Creating user account get username and password that you have entered and then implement like this.
if ($user = authenticate_user_login($username, $password)) {
/// Let's get them all set up.
complete_user_login($user);
redirect($CFG->wwwroot . 'URL you want');
}
I need to do some extra checks on a user, I would like to get the user by username and password.
Firstly:
Is there a built in function that gets a user by username and password without authenticating them?
Secondly:
If the above is no, then how do I correctly hash the password, because if I use Hash::make( $password ) and then compare to the database, it is not the same... You would usually use Hash::check but I need to actually get the user by username and password.
In Laravel 5.2
You can use Auth::once($credentials) to validate credentials and thereafter Auth::getUser(); to get the user.
$credentials = Request::only('username', 'password');
if(!Auth::once($credentials)) {
// Invalid user credentials; throw Exception.
}
$user = Auth::getUser();
First:
If you want to check if user data to authentication is correct you can use:
if (Auth::validate($credentials))
{
//
}
But if you want to get user from database with user and password, you can use:
$user = User::whereName($username)->wherePassword(Hash::make($password))->first();
Second
To store password in database you should use Hash::make($password) as you showed and it works without any problems. Using Auth::validate should solve the issue.
Yes, there is a built in function you should use. I recommend you to read the docs. But here's a good example, it's pretty self-evident:
$input = array(
'username' => Input::get('username'),
'password' => Input::get('password'),
);
$remember = (boolean)Input::get('remember'); //'Remember me' checkbox
if (Auth::attempt($input, $remember)) {
return Redirect::intended('dashboard')->with("success", "You're logged in!"); //Redirect the user to the page intended to go to, with the dashboard page as default
}
Registering a user looks something like this:
$input = array(
'username' => Input::get('username'),
'email' => Input::get('email'),
'password' => Hash::make(Input::get('password')) //Encrypt password
);
$user = User::create($input);
I also recommend you to read about input validation. I hope this helps, good luck.
Edit: I didn't read the "without authenticating them" part. You should use Auth::validate($input) as Marcin already explained.
Laravel 5.7
To check a users credentials without logging them in, I had to do this:
$user = User::whereEmail($request->email)->first();
$user = password_verify($request->password, optional($user)->getAuthPassword()) ? $user : false;
Laravel auth validation makes use of https://www.php.net/manual/en/function.password-verify.php