Chrishon Wyllie Chrishon Wyllie - 2 months ago 32
Javascript Question

How to maintain Firebase Auth for multiple pages on the web?

I am using Firebase for a web application. The goal is to allow a familiar log-in/sign-up where the user signs up or logs in one one page, and upon successful authentication, is brought to the home page.

The flow would look something like this:
Log-in/Sign-up -> (allows access to) -> [Home, Profile, Search, Friends, etc.]

I am using Javascript (No AngularJs since I am unfamiliar with it entirely). The problem I am having is that once the user successfully logs in or signs up, their "user object" becomes null on using

window.location = 'home.html'


Here is the complete code. I am using the sample found Firebase for now for the authentication process, but the home.html is my doing:

<!DOCTYPE html>
<html>
<head>

<!--Bootstrap CSS CDN-->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!---jQuery CDN-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>






<script type="text/javascript">
/**
* Handles the sign in button press.
*/
function toggleSignIn() {
if (firebase.auth().currentUser) {
// [START signout]
firebase.auth().signOut();
// [END signout]
} else {
var email = document.getElementById('email').value;
var password = document.getElementById('password').value;
if (email.length < 4) {
alert('Please enter an email address.');
return;
}
if (password.length < 4) {
alert('Please enter a password.');
return;
}
// Sign in with email and pass.
// [START authwithemail]
firebase.auth().signInWithEmailAndPassword(email, password).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// [START_EXCLUDE]
if (errorCode === 'auth/wrong-password') {
alert('Wrong password.');
} else {
alert(errorMessage);
}
console.log(error);
document.getElementById('quickstart-sign-in').disabled = false;
// [END_EXCLUDE]
});
// [END authwithemail]
window.location = '/1home.php'
}
document.getElementById('quickstart-sign-in').disabled = true;
}
/**
* Handles the sign up button press.
*/
function handleSignUp() {
var email = document.getElementById('email').value;
var password = document.getElementById('password').value;
if (email.length < 4) {
alert('Please enter an email address.');
return;
}
if (password.length < 4) {
alert('Please enter a password.');
return;
}
// Sign in with email and pass.
// [START createwithemail]
firebase.auth().createUserWithEmailAndPassword(email, password).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// [START_EXCLUDE]
if (errorCode == 'auth/weak-password') {
alert('The password is too weak.');
} else {
alert(errorMessage);
}
console.log(error);
// [END_EXCLUDE]
});
// [END createwithemail]
}
/**
* Sends an email verification to the user.
*/
function sendEmailVerification() {
// [START sendemailverification]
firebase.auth().currentUser.sendEmailVerification().then(function() {
// Email Verification sent!
// [START_EXCLUDE]
alert('Email Verification Sent!');
// [END_EXCLUDE]
});
// [END sendemailverification]
}
function sendPasswordReset() {
var email = document.getElementById('email').value;
// [START sendpasswordemail]
firebase.auth().sendPasswordResetEmail(email).then(function() {
// Password Reset Email Sent!
// [START_EXCLUDE]
alert('Password Reset Email Sent!');
// [END_EXCLUDE]
}).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// [START_EXCLUDE]
if (errorCode == 'auth/invalid-email') {
alert(errorMessage);
} else if (errorCode == 'auth/user-not-found') {
alert(errorMessage);
}
console.log(error);
// [END_EXCLUDE]
});
// [END sendpasswordemail];
}
/**
* Handles registering callbacks for the auth status.
*
* This method registers a listener with firebase.auth().onAuthStateChanged. This listener is called when
* the user is signed in or out, and that is where we update the UI.
*
* When signed in, we also authenticate to the Firebase Realtime Database.
*/
function initApp() {
// Listening for auth state changes.
// [START authstatelistener]
firebase.auth().onAuthStateChanged(function(user) {
// [START_EXCLUDE silent]
document.getElementById('quickstart-verify-email').disabled = true;
// [END_EXCLUDE]
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 refreshToken = user.refreshToken;
var providerData = user.providerData;
// [START_EXCLUDE silent]
document.getElementById('quickstart-sign-in-status').textContent = 'Signed in';
document.getElementById('quickstart-sign-in').textContent = 'Sign out';
document.getElementById('quickstart-account-details').textContent = JSON.stringify({
displayName: displayName,
email: email,
emailVerified: emailVerified,
photoURL: photoURL,
isAnonymous: isAnonymous,
uid: uid,
refreshToken: refreshToken,
providerData: providerData
}, null, ' ');
if (!emailVerified) {
document.getElementById('quickstart-verify-email').disabled = false;
}
// [END_EXCLUDE]
} else {
// User is signed out.
// [START_EXCLUDE silent]
document.getElementById('quickstart-sign-in-status').textContent = 'Signed out';
document.getElementById('quickstart-sign-in').textContent = 'Sign in';
document.getElementById('quickstart-account-details').textContent = 'null';
// [END_EXCLUDE]
}
// [START_EXCLUDE silent]
document.getElementById('quickstart-sign-in').disabled = false;
// [END_EXCLUDE]
});
// [END authstatelistener]
document.getElementById('quickstart-sign-in').addEventListener('click', toggleSignIn, false);
document.getElementById('quickstart-sign-up').addEventListener('click', handleSignUp, false);
document.getElementById('quickstart-verify-email').addEventListener('click', sendEmailVerification, false);
document.getElementById('quickstart-password-reset').addEventListener('click', sendPasswordReset, false);
}
window.onload = function() {
initApp();
};
</script>
</head>

<body>
<div class="jumbotron text-center">

</div>

<div class="container">
<div class="jumbotron">

<div class="row">
<div class="col-md-6">
<!--<img src="" style="width:500px; height:340px">-->

</div>

<div class="col-md-6">

<!-- Container for the demo -->
<div class="mdl-card mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-cell--12-col-tablet mdl-cell--12-col-desktop">
<div class="mdl-card__title mdl-color--light-blue-600 mdl-color-text--white">
<h2 class="mdl-card__title-text">Sign Up</h2>
</div>

<div class="mdl-card__supporting-text mdl-color-text--grey-600">
<p>Enter an email and password below and either sign in to an existing account or sign up</p>

<input class="mdl-textfield__input" style="display:inline;width:auto;" type="text" id="email" name="email" placeholder="Email"/>
&nbsp;&nbsp;&nbsp;
<br /><br />
<input class="mdl-textfield__input" style="display:inline;width:auto;" type="password" id="password" name="password" placeholder="Password"/>
<br/><br/>
<button disabled class="mdl-button mdl-js-button mdl-button--raised" id="quickstart-sign-in" name="signin">Sign In</button>
&nbsp;&nbsp;&nbsp;
<button class="mdl-button mdl-js-button mdl-button--raised" id="quickstart-sign-up" name="signup">Sign Up</button>
&nbsp;&nbsp;&nbsp;
<button class="mdl-button mdl-js-button mdl-button--raised" disabled id="quickstart-verify-email" name="verify-email">Send Email Verification</button>
&nbsp;&nbsp;&nbsp;
<button class="mdl-button mdl-js-button mdl-button--raised" id="quickstart-password-reset" name="verify-email">Send Password Reset Email</button>

<!-- Container where we'll display the user details -->
<div class="quickstart-user-details-container">
<!--Firebase--> sign-in status: <span id="quickstart-sign-in-status">Unknown</span>
<div><!--Firebase--> auth <code>currentUser</code> object value:</div>
<pre><code id="quickstart-account-details">null</code></pre>
</div>
</div><!---->
</div>

</div>
</div>

</div>



<!--Bootstrap Js CDN-->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<!--Firebase Initialization-->
<script src="https://www.gstatic.com/firebasejs/3.2.1/firebase.js"></script>
<script>
// Initialize Firebase
var config = {
apiKey: "XXXXXXXXXXXXXXXXX",
authDomain: "XXXXXXXXXXXXXX",
databaseURL: "XXXXXXXXXXXXX",
storageBucket: "XXXXXXXXXXXXXXXX",
};
firebase.initializeApp(config);
</script>



</body>
</html>


Additionally, the page that is auth screen redirects to is monitoring the auth state with
onAuthStateChanged
. This is where using
console.log(user);
returns null, although using
console.log("Attempted sign in);
is printed. I copied the initApp function from the Firebase Auth sample. Perhaps I am using it in the wrong place?

<!DOCTYPE html>
<html>
<head>

<meta name ="viewport" content ="width=device-width, initial-scale=1.0">
<!--Bootstrap CSS CDN-->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!---jQuery CDN-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="animations.css">


<!--Firebase-->
<script type="text/javascript">

function initApp() {
// Listening for auth state changes.
// [START authstatelistener]
firebase.auth().onAuthStateChanged(function(user) {
// [START_EXCLUDE silent]
// [END_EXCLUDE]
console.log("Attempted Sign in");
console.log(user);
if (user) {
// User is signed in.
console.log("Attempted Sign in successful");
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 refreshToken = user.refreshToken;
var providerData = user.providerData;


console.log(uid);
console.log(displayName);
console.log(email);
console.log(photoURL);



// [START_EXCLUDE silent]

if (!emailVerified) {
}
// [END_EXCLUDE]
} else {
// User is signed out.
// [START_EXCLUDE silent]

// [END_EXCLUDE]
}
// [START_EXCLUDE silent]
// [END_EXCLUDE]
});
// [END authstatelistener]

}
window.onload = function() {
initApp();
// Register the callback to be fired every time auth state changes
ref.onAuth(function(authData) {
if (authData) {
console.log("User " + authData.uid + " is logged in with " + authData.provider);
} else {
console.log("User is logged out");
}
});
};
</script>


So, to re-iterate the issue and goal: I want to be able to authenticate a user on this page (the code above represents a login/signup screen), and then send them a set of pages that loads content based on their Firebase ID.

Answer

I think you're calling your redirect too early. Try placing it in the onAuthStateChanged callback. If you redirect before your local Firebase client has had time to register the authentication change, your session won't have time to get stored in localStorage, so there won't be any session when you arrive at your destination. The login process is effectively short-circuited.

Try something like

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
   window.location = '/1home.php';
  }
}
Comments