I have a page in which I sign in a user using email n password.after that based on the user.uidthat would be returned I push in say page_one or page_two. the signInWithEmailAndPassword() method returns null if email and password has some error else it returns the user uid so i did something like this:
if(user.uid != null){
//home page
page_one;
}
else if (user.uid == null){
//error page
page_two;
}
the problem I get is that whether I sign in with correct email and password or not it pushes me to page_two and then on back press it sends me to page_onetho there is no route/navigation between them
Related
I am working on a web app with an existing user base. Email verification was not initially implemented in the sign in flow.
I have successfully added code for sending verification email for all new sign ups but I also wanted to make a small page (or modal) where current users would be shown a button that would send the verification link to their inbox
The current sign up flow where I created the user with createUserWithEmailAndPassword I was able to get access to the user.user.sendEmailVerification method to do so, but cannot find any way to access this method to implement the feature for existing users.
Is there a way to access the sendEmailVerification method after the user has been created?
I am assuming that it would be available within the onAuthStateChange trigger but implementing that would lead to a bad UX (as I do not want to prompt the users everytime they login)
Edit:
I know the documentation states that we can use the firebase.auth().currentUser to get the current user but that, for some reason did not work.
Also, I found references online suggesting to no longer use that method and they mentioned to use the onAuthStateChange method instead, which is why I was looking into that approach
You can try this method:
const btnVerifyEmail = document.getElementById("btn-verify-id")
btnVerifyEmail.onclick = function () {
const user = firebase.auth().currentUser;
user.sendEmailVerification().then(function() {
// Email sent.
console.log("Email Sent")
}).catch(function(error) {
// An error happened.
console.log(error)
});
}
It's mentioned in the documentation right here
The sendEmailVerification() should not be called in the onAuthStateChanged event because it would blast out an email on every page load if the user's email isn't verified.
You should instead display a notification on the page if User.emailVerified is false that contains a link to send the user an email.
Here's a working example:
// On page load watch for auth state changes
firebase.auth().onAuthStateChanged(function(user) {
// If the user is logged in
if (user) {
// If the user's email isn't verified
if (!user.emailVerified) {
// Show the notification bar that informs the user that they need to validate
// their email by clicking a link. Let's pretend the link looks like this:
// Send me a verification email
showNotification();
}
}
});
// Function attached to your link's onclick event
function sendEmailVerification() {
// Retrieve the current user
const user = firebase.auth().currentUser;
// If user's email is already verified, exit
if (user.emailVerified) {
return;
}
// Tell Firebase to send the verification email and discard the promise
user.sendEmailVerification().then().catch();
}
Dharmaraj's answer is good but this is a full example.
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.
My use case is that I want to ask newly signed up users to enrich basic info like their names.
So I was hoping to do it like:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
if (some indicator tells me it is newly signed up user)
{redirect to a form to fill in more info}
} else {
// No user is signed in.
}
});
I checked the doc, and could not find anything related to this...
Thanks for the help in advance.
Since version 4.6.0: https://firebase.google.com/support/release-notes/js#4.6.0
You can get if a user is new or existing in 2 ways:
If you are getting back a UserCredential result, check result.additionalUserInfo.isNewUser
Check firebase.auth().currentUser.metadata.creationTime === firebase.auth().currentUser.metadata.lastSignInTime
Previously you had to do that on your own and keep track of the user using Firebase Realtime Database. When a user signs in, you check if a user with the specified uid exists in the database or not. If the user was not found, it is a new user, you can then add the user to the database. If the user is already in the database then this is a returning existing user. Here is an example in iOS.
Handing Firebase + Facebook login process
Example for using result.additionalUserInfo.isNewUser:
firebase.auth().signInWithPopup(provider).then((result) => {
console.log(result.additionalUserInfo.isNewUser);
});
One thing you can do is do things in the callback function of the signup function, the signup function do return a promise. You can do something like this:
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(function(user) {
//I believe the user variable here is the same as firebase.auth().currentUser
//take the user to some form you want them to fill
})
.catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
However, I don't really recommend doing it this way because the client side code can be unreliable. Think about what if a user suddenly disconnect before they can fill the form. Their data will be incomplete in your database. So if you do it this way, do set a flag in your user's profile when they submit the form so that you know who filled detailed information and who didn't.
Another better way to do this is using firebase cloud functions. You can have code like this in your cloud functions. Cloud functions are written in node.js so you don't need to spend time on another language.
exports.someoneSignedUp = functions.auth.user().onCreate(event => {
// you can send them a cloud function to lead them to the detail information form
//or you can send them an welcome email which will also lead them to where you want them to fill detailed information
});
This way is much better because you can safely assume that your cloud functions server will never be down or compromised. For more information about cloud functions you can refer to their doc: https://firebase.google.com/docs/functions/auth-events
You can check the sign-in methods the user has (if any). If there are none, it is a new user.
// Fetch sign in methods (if any)
Auth.auth().fetchSignInMethods(forEmail: userEmail!) { [self] signInMethodsArray, error in
// Check for error and alert user accordingly
if let error = error {
// handle errors
}
// Email accepted.
// Check if new or returning user.
else {
if (signInMethodsArray == nil) {
// New User
}
else {
// Returning User
}
}
}
This is Swift (iOS) code, but the concept is the same across languages.
I am using membership api to fetch the user password and email.
I have got this code:
MembershipUser currentUser = Membership.GetUser();
UserPasssword.Text = currentUser.GetPassword(); //Null exception
I need to check the user at the login. The problem is that the user isnt login. So I thought to find a way to fetch the user password or email with the membership api and not through the a database query. Is there a way to do it? or do I have to resort to a database query?
Remember that the user isnt logged in .. .. So the result will be null point exception each time on the currentUser object..
How can check his email with the membership api and then use a redirection:
if (currentUser.Email == LoginEmail.Text && currentUser.GetPassword() == hash)
{
FormsAuthentication.RedirectFromLoginPage(currentUser.UserName, false);
}
else
{
LoginFail.Text = "Email or Password havent been incorrect.";
}
If you're just trying to log the user in, you'd be better off letting membership handle it via the Validate User method.
To get the Email and Password of a user, you can use Membership.GetUser(username). This method returns a MembershipUser object that you can query Email and GetPassword().
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.