I am writing a password-reset page for my website. Here's my idea:
a. User click the "forgot password" link on the login page
b. Redirect to my password-reset page
c. User enter his email address
d. A email message sent to the email address with the link to reset his/her password. The link has security code like ?code="xxxx" in it.
e. User open the link and enter new password, and then click the submit button.
f. My page change user's password.
My question is for step f. In step e, when user opened the link, I could verify his security code and then show the 'new password' and the 'confirm password' fields to user. But when the user clicked the submit button, how could I know this is a real request submited by the user instead of a hacker? Maybe I am wrong, but I think hacker can easily simulate such field data, since there is no validation fields.
There are some idea I can think of to validate the request in step f, but I don't know whether they are right.
1. Add a encrypted cookie in step e and check it in step f?
2. Use a session variable in step e and check it in step f?
3. Add a hidden field in step e and check it in step f?
Are those approaches ok? Which one is better, or is there any better one?
Thanks in advance.
A user entering their username and reset code should log them into the site just as their username and password would. The difference is you then immediately force them to change their password. With this password reset method you're implicitly trusting that the user is the owner of the email account where the code was sent.
Edit:
Ok, so I don't know the first thing about ASP.net.
However, I've handled this problem many times before. Here is a solution of mine in PHP:
<?php
class AuthController extends Zend_Controller_Action
{
public function identifyAction()
{
if ($this->_request->isPost()) {
$username = $this->_getParam('username');
$password = $this->_getParam('password');
if (empty($username) || empty($password)) {
$this->_flashError('Username or password cannot be blank.');
} else {
$user = new User();
$result = $user->login($username, $password);
if ($result->isValid()) {
$user->fromArray((array) $this->_auth->getIdentity());
if ($this->_getParam('changepass') || $user->is_password_expired) {
$this->_redirect('auth/change-password');
return;
}
$this->_doRedirect($user);
return;
} else {
$this->_doFailure($result->getIdentity());
}
}
}
$this->_redirect('/');
}
public function forgotPasswordAction()
{
if ($this->_request->isPost()) {
// Pseudo-random uppercase 6 digit hex value
$resetCode = strtoupper(substr(sha1(uniqid(rand(),true)),0,6));
Doctrine_Query::create()
->update('dUser u')
->set('u.reset_code', '?', array($resetCode))
->where('u.username = ?', array($this->_getParam('username')))
->execute();
$mail = new Zend_Mail();
$mail->setBodyText($this->_resetEmailBody($this->_getParam('username'), $resetCode));
$mail->setFrom('no-reply#example.com', 'Example');
$mail->addTo($this->_getParam('username'));
$mail->setSubject('Forgotten Password Request');
$mail->send();
$this->_flashNotice("Password reset request received.");
$this->_flashNotice("An email with further instructions, including your <em>Reset Code</em>, has been sent to {$this->_getParam('username')}.");
$this->_redirect("auth/reset-password/username/{$this->_getParam('username')}");
}
}
public function resetPasswordAction()
{
$this->view->username = $this->_getParam('username');
$this->view->reset_code = $this->_getParam('reset_code');
if ($this->_request->isPost()) {
$formData = $this->_request->getParams();
if (empty($formData['username']) || empty($formData['reset_code'])) {
$this->_flashError('Username or reset code cannot be blank.');
$this->_redirect('auth/reset-password');
} elseif ($formData['new_password'] !== $formData['confirm_password']) {
$this->_flashError('Password and confirmation do not match.');
$this->_redirect('auth/reset-password');
} else {
$user = new User();
$result = $user->loginWithResetCode($formData['username'], $formData['reset_code']);
if ($result->isValid()) {
$user->updatePassword($result->getIdentity(), $formData['new_password']);
$user->fromArray((array) $this->_auth->getIdentity());
$this->_setLegacySessionData($user);
$this->_flashNotice('Password updated successfully!');
$this->_doRedirect($user);
} else {
$this->_doFailure($result->getIdentity());
$this->_redirect('auth/reset-password');
}
}
}
}
protected function _doFailure($username)
{
$user = Query::create()
->from('User u')
->select('u.is_locked')
->where('u.username = ?', array($username))
->fetchOne();
if ($user->is_locked) {
$lockedMessage = Config::get('auth.lock_message');
if (!$lockedMessage) {
$lockedMessage = 'This account has been locked.';
}
$this->_flashError($lockedMessage);
} else {
$this->_flashError('Invalid username or password');
}
}
}
If you can follow this, it should give you a good idea of what to do. I'll try to summarize:
identifyAction
This is the regular "login" using username and password. It logs the user in and stores their identity in the session.
forgotPasswordAction
This presents the user with a form requesting their username. After entering their username a reset code is generated, stored in their entry in the user table, and they are emailed as well as redirected to the reset password page. This page is unauthenticated, the user is not logged in.
resetPasswordAction
This is where the user is presented with the "resetPassword" form. They must provide their username and the reset code they received via email. This authenticates the user with the given username and reset code, just as if the reset code were a password. If the credentials are valid the user is then redirected to the changePassword action where they are permitted to change their password. The changePasswordAction (not shown) requires the user be authenticated (logged in) either via username/password or username/resetCode
Hope this helps.
If your code that you're emailing is a GUID or some such ID, there is a statistically low chance that someone can guess that code. If you additionally had the link include a hashed version of their email or some other way of linking the code to the user, I think you'd be pretty well safe from malicious input.
I'd be more worried about people being spammed from step c/d, unless you're doing some sort of verification of the email existing currently in your database.
Related
i'm trying to validate my email before the user can enter to the home page.
the problem is when i fill the email and password user with aaany thing it give the access without any check.
here is my code for sign in page
and this is the code of sign up screen
If it is all about validating the email for formatting, then what you can do is shown below. Put it in your email address validator you are submitting the data for Login/Register
validator: (value){
Pattern pattern = r'^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regex = new RegExp(pattern);
// Null check
if(value.isEmpty){
return 'please enter your email';
}
// Valid email formatting check
else if(!regex.hasMatch(value)){
return 'Enter valid email address';
}
// success condition
else {
email = value;
}
return null;
}
You will be good to go with this :) Happy learning.
I'm getting started with Firebase and I would like to have a suggestion concerning the best way to force a user to be logged to use my website.
I'm building a very simple app but i have to guarantee that content can be displayed only to logged people
Thank you!
Use auth().onAuthStateChanged
https://firebase.google.com/docs/auth/web/start#set_an_authentication_state_observer_and_get_user_data
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
var displayName = user.displayName;
var email = user.email;
var emailVerified = user.emailVerified;
var photoURL = user.photoURL;
var isAnonymous = user.isAnonymous;
var uid = user.uid;
var providerData = user.providerData;
// ...
} else {
// User is signed out.
// ...
}
});
I assume you are using PHP to build your firebase website, in php there are session tokens that can be used to auto log in. once you got a session login you could use that to redirect them to the login page if they are not logged in. here a snip of code from one of my old college projects.
if(!isset($_SESSION['user_logged_in'])){
header("Location: ../login.php");
}else{
if($_SESSION['user_logged_in'] != true){
header("Location: ../login.php");
}
}
its been a while but this checks if I remember correctly the first line checks if there is no session token and the second line checks to see if that person is logged in. if either of this isn't true it will load the login page instead of the page they wanted and cause its all done in php they can't get around this. we put all this in an authentication template, I have uploaded the PHP file to google drive if you wish to example how logins are done, this is using an MYOB database so you will have to convert it but the code in here should be a good example.
https://drive.google.com/open?id=1_oKWU3LnpmfJg2pD5kHzYxFX2Ydl42e_
hope this helps
At the moment this is a general question with no code as I am looking for a BEST practices example to my question:
User issues an email change request. (done)
A link is sent to the new address to confirm the new email. (done)
User clicks the confirmation link and the DB update is complete. (done)
What also needs to happen is when the confirmation link is sent for the change, an email should also be sent to the original email address where the user can click a link to reverse the process for whatever reason. I would think also that even if the new email address was accepted, if the original link denies the change it reverts and 2) if the original email reverts and then the new email link is confirmed, that the request would then be denied.
Any direction or code on this matter would be greatly appreciated.
Seems like a simple bit field in the database user record would suffice, or an associated database record would work too. When both emails are sent, mark the field for that user, let's call it "ChangeEmailSent" to 1. When either email is clicked, the field should be updated to 0. The actual changing of the email should only occur if the field is 1.
Some pseudo-code if you like
private void CancelEmailChange(email)
{
var user = Database.GetUser(email);
user.ChangeEmailSent = false;
Database.Save();
}
private void ProcessEmailChange(email)
{
var user = Database.GetUser(email);
if (user.ChangeEmailSent)
{
user.email = getNewEmailAddress(); //whatever logic for a new email
user.ChangeEmailSent = false;
Database.Save();
}
}
I can't figure out why my WebSecurity.ChangePassword is not working. Here's the piece of code I'm working on.
if (WebSecurity.ChangePassword(USER, oldpass, password)) {
Response.Redirect("~/SuperAdmin");
return;
}else {
ModelState.AddFormError(USER);
// I put the each WebSecurity.ChangePassword parameter to this parameter to check whether
//each parameter valid or not (print it out)
}
and for each parameter of WebSecurity.ChangePassword, I retrieve it from the database as follows
if(IsPost){
Validation.RequireField("email", "Masukkan email");
Validation.RequireField("password", "Masukkan Password");
Validation.RequireField("userid", "user ID tidak ada!");
email = Request.Form["email"];
password = Request.Form["password"];
userId = Request.Form["userId"];
if(Validation.IsValid()){
var db = Database.Open("StarterSite");
var updateCommand2 = "UPDATE UserProfile SET Email=#0 WHERE UserId=#1";
db.Execute(updateCommand2, email,userId);
var USER = db.QueryValue("SELECT a.Email FROM UserProfile a, webpages_Membership b WHERE a.UserId=b.UserId AND a.UserId= #0", userId);
var oldpass = db.QueryValue("SELECT Password FROM webpages_Membership WHERE UserId = #0", userId);
Can anyone tell me what seems to be the problem here? Thanks in advance
The WebPages Membership has everything built you do not need to get the users email address and password (I am guessing the email address is the username right?) The ChangePassword method takes 3 arguments. which is UserName, CurrentPassword, NewPassword.
The reason your getting false is because your getting the old password from the database based on the users current Id, but the old password does not match the users current password because old one is encrypted and you're not encrypting the one they submit (in fact you don't even have a field for them to enter their current password).
The WebPages Membership provider will do all the updating you do not need open the database and update the users password, the weird thing you're doing is telling the user to enter a new password but not asking for the current one! Here see this for more information:
http://www.thecodingguys.net/reference/asp/websecurity-changepassword
Make sure the user you are trying to change password for is not LockedOut. You can check it by this
select * from aspnet_membership
where
IsLockedOut = 1
I am designing a math problem site using Firebase and I want to display a problem when someone logs in.
What I want in pseudo code is,
if user logged in
document.write([problem])
else
document.write(Please login to see the problem)
Any ideas?
When using Firebase Simple Login, upon instantiation of the FirebaseAuthClient you will define a callback function that is invoked any time the login state of the user changes.
From https://www.firebase.com/docs/security/simple-login-overview.html:
var chatRef = new Firebase('https://SampleChat.firebaseIO-demo.com');
var authClient = new FirebaseAuthClient(chatRef, function(error, user) {
if (user) {
// user authenticated with Firebase
} else if (error) {
// an error occurred authenticating the user
} else {
// user is logged out
}
});
For your case, if you have a user object, you can hide any login-related UI and show the problem, otherwise, hide the problem and show any login-related UI.
Then, to log users in, choose one or more of the Firebase Simple Login authentication providers, configure that provider in Forge (accessed via https://<your-firebase>.firebaseio.com) and attempt to authenticate the user via:
authClient.login(<provider>, <options>);
I hope that helps!