Firebase web sign out doesn't send any XHR - javascript

When setting up a simple form - 2 buttons with 2 functions to test firebase's auth, i have a problem with sign out.
The sign in function works perfect.
However, sign out doesn't send any XHR. Nothing, nada. No errors.
But the promise resolves.
The console logs 'Signed Out'.
What am i doing wrong?
Thanks!
function signIn() {
firebase.auth().signInWithEmailAndPassword('email#email.com', 'password')
.then(() => {
console.log('Logged in')
})
.catch((error) => {
var errorCode = error.code;
var errorMessage = error.message;
console.log(errorMessage)
});
}
function signOut() {
firebase.auth().signOut().then(() => {
console.log('Signed out!')
}).catch((error) => { console.log(error) });
}

Signing out just involves "forgetting" the refresh token that's used to keep the user signed in persistently over time. The server doesn't need to be notified that this happened.

Related

Passwordless sign in is not working in Firebase

Passwordless sign in is not working in Firebase. Email was sent successfully. But after clicking on the link provided in the email that link redirects to the website with api key, mode etc. But not signing in or saving the email in firebase.
Please help me!!
const handleContinueWithEmail = async (event: any) => {
event.preventDefault();
setSignInLoading(true);
if (isSignInWithEmailLink(auth, window.location.href)) {
setEmail(window.localStorage.getItem("emailForSignIn"));
if (!email) {
setEmail(window.prompt("Please provide your email for confirmation"));
}
signInWithEmailLink(auth, email, window.location.href)
.then((result) => {
window.localStorage.removeItem("emailForSignIn");
// You can access the new user via result.user
// Additional user info profile not available via:
// result.additionalUserInfo.profile == null
// You can check if the user is new or existing:
// result.additionalUserInfo.isNewUser
console.log(result.user);
})
.catch((error) => {
// Some error occurred, you can inspect the code: error.code
// Common errors could be invalid email and invalid or expired OTPs.
console.log(error);
});
} else {
sendSignInLinkToEmail(auth, email, {
url: location.origin,
handleCodeInApp: true,
})
.then(() => {
window.localStorage.setItem("emailForSignIn", email);
setSignInLoading(false);
setShowSuccessToast(true);
setSuccessText(
"Sign in email has been sent! Check spam folder if not found."
);
setTimeout(function () {
setShowSuccessToast(false);
}, 6000);
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
setSignInLoading(false);
console.error(errorCode, errorMessage);
});
}
};
Successfully redirected with API key, mode, and more. But not sign in or saving email on Firebase.
I'm trying to add passwordless sign in using fireabase on my website. But it's not sign in or saving email to firebase user list. So, I need help to solve this problem.

disable firebase Auth State Persistence

I have this login function currently:
AuthorizationHome.doSignInWithEmailAndPassword(email, password)
.then(() => {
firebase.auth().onAuthStateChanged((user) => {
..........
But it basically keeps my session logged in even when I close my browser, restart my computer, it does it all. Because the user is able to manage their payments from my app, I need to make sure that if they close the browser, it logs them out.
Firebase docs tells me to do it like this:
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.SESSION)
.then(() => {
return firebase.auth().signInWithEmailAndPassword(email, password);
})
.catch((error) => {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
});
It is different then my original code, so I am not sure how to do this. I'm totally new to the way firebase works so I am a little confused.
Are you trying to execute firebase.auth().onAuthStateChanged after AuthorizationHome.doSignInWithEmailAndPassword(email, password) successfully resolves?
firebase
.auth()
.setPersistence(firebase.auth.Auth.Persistence.SESSION)
.then(() => {
return AuthorizationHome.signInWithEmailAndPassword(email, password).then(() => {
firebase.auth().onAuthStateChanged((user) => { /* do things */ });
});
})
.catch((error) => {
// Handle Errors here.
const errorCode = error.code;
const errorMessage = error.message;
});
That being said, you can probably run setPersistence(firebase.auth.Auth.Persistence.SESSION) as part of app initialization separately. It doesn't have to be run right before every execution of doSignInWithEmailAndPassword:
// app initialization
firebase
.auth()
.setPersistence(firebase.auth.Auth.Persistence.SESSION)
// somewhere else on demand
AuthorizationHome.doSignInWithEmailAndPassword(email, password)
.then(() => {
firebase.auth().onAuthStateChanged((user) => {
Hopefully that helps!

firebase sendEmailVerification does not give error on non exisent email address

I'm developing an authentication system for my React app with Firebase Auth. When the user signs up, firebase auth registers the user (createUserWithEmailAndPassword) and returns a promise with auth.uid and auth.emailVerified set to "false". This is fine.
I then use sendEmailVerification() method so the email address can be verified. I've tested the code and it works ok for a "valid" and "existing" email address. "catch" does give error for duplicate email address as expected. The problem is, it does not send the NON-EXISTING email (which I suppose is the correct bahaviour) but its should then give an error (so I can display to the user) which it does not.
Can someone explain why I'm not getting error for NON EXISTENT email address?
export const unpSignUp = (newUser) => {
console.log("newUser", newUser);
return (dispatch, getState, { getFirebase, getFirestore }) => {
const firebase = getFirebase();
const firestore = getFirestore();
firebase.auth().createUserWithEmailAndPassword(
newUser.unp_a05_email,
newUser.unp_a10_password
)
.then((response) => {
return firestore
.collection("unps")
.doc(response.user.uid)
.set({
unp_a02_surname: newUser.unp_a02_surname,
unp_a03_name: newUser.unp_a03_name,
unp_a06_verify_email_sent_datetime: null,
unp_a07_email_verified_on_datetime: null,
unp_a18_acc_created_on_datetime: moment().format("YYYY MM DD HH:mm:ss"),
});
})
.then((response) => {
console.log("SIGNUP SUCCESS ", response);
// user has been signed up, next step is to send verification email
dispatch({ type: SIGNUP_SUCCESS })
})
.then(() => {
// user has been signed up, next step is to send verification email
console.log('send email adr verification')
return firebase.auth().currentUser.sendEmailVerification()
})
.then( (response) => {
console.log("Verification email sent", response);
const user = firebase.auth().currentUser
console.log('current user', user)
const unp = firestore.collection("unps").doc(user.uid);
return unp.update({
unp_a06_verify_email_sent_datetime: moment().format("YYYY MM DD HH:mm:ss"),
})
})
.then( () => {
console.log(`unp_a06_verify_email_sent_datetime update to ${moment().format("YYYY MM DD HH:mm:ss")} `)
})
.catch((error) => {
console.log("SIGNUP ERROR", error);
console.log("SIGNUP ERROR CODE", error.code);
console.log("SIGNUP ERROR MESAGE", error.message);
dispatch({ type: SIGNUP_ERROR, error });
});
};
};
From firebase reference,
the return type of sendEmailVerification is Promise<void> - and it does not tell about any error codes that are sent in case of wrong email or failed/bounce mails. The error code it mentions is with respect to actionCodeSettings
If the actionCodeSettings is not specified, no URL is appended to the action URL. The state URL provided must belong to a domain that is whitelisted by the developer in the console. Otherwise an error will be thrown.
Thus it can not be checked if it is a valid email id. (This is expected behaviour as receiving mail servers may be down at times and hence there is a concept of retrying bounce mails)

After signing out, my firebase idToken is still valid?

I have the following code in my firebase front-end:
document.querySelector('#sign-out').addEventListener('click', () => {
firebase.auth().signOut().then(() => {
document.location = '/sign-in';
}, (error) => {
console.error('Sign Out Error', error);
});
})
This seems to be working. I see the network request succeed, and the redirect to /sign-in occurs.
However, when I then navigate to /chatroom, I am considered logged in. My python/flask backend has the following code on the endpoint:
#app.route("/chatroom")
def chatroom():
if 'idToken' in request.cookies:
id_token = request.cookies.get("idToken")
try:
decoded_token = auth.verify_id_token(id_token)
except:
print("INVALID TOKEN")
return redirect(url_for("sign_in"))
return render_template("chatroom.html")
else:
return redirect(url_for("sign_in"))
Rather than redirecting the user to /sign-in when I hit this path, Firebase is verifying that the token is valid and so I am allowed to proceed, even though I had logged out.
What am I missing?
Edit:
Changed code to this for debugging purposes:
firebase.auth().signOut().then(() => {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
console.log('still signed in');
} else {
console.log('signed out');
}
});
}, (error) => {
console.error('Sign Out Error', error);
});
It outputs signed out.....so I'm quite confused.
Signing out does not invalidate the token. It just causes the SDK to forget about it, so it doesn't get refreshed or passed along to other Firebase products automatically. The old token will be valid for up to 1 hour, until it needs to be refreshed. If not refreshed, then it will fail verification.
If you are saving the ID token in a cookie, you should also remove it from the cookie in order to effectively sign out, so it doesn't get passed along to your backend.

Firebase Anonymous User once upgraded

I'm implementing a workflow where every user using my app is an anonymous user until they sign-in/up (either email or Google).
To sign up, it's straightforward: I use linkWithPopup.
However, I had some issues with user signing in: I try to link them and, if I get the auth/credential-already-in-use error (happens if the user upgrades once, signs out and then try to sign in again), I sign them in.
firebase.auth().currentUser.linkWithPopup(provider).then(function (result) {
var token = result.credential.accessToken;
// The signed-in user info.
var user = result.user;
// ...
}).catch(function (error) {
// Handle Errors here.
var errorCode = error.code;
if (errorCode === 'auth/credential-already-in-use') {
return firebase.auth().signInWithCredential(error.credential);
}
}).then((result) => {
return dispatch(loadContent(result.user.uid))
}).then(() => {
history.push('/');
});
The code above is working great and that's less hassle than doing it all by myself.
However, how do I remove the anonymous users which are created and orphan in case the user signs in?
I tried to make a reference to the old useless anonymous user and to delete it once the user is signed in (and so, changed its account) but it is obviously not working because the account changed and that would be a big security flaw if a user could delete another one...
I'm not very familiar with Firebase ecosystem, how should I handle that? Do I need to use a combination of Firebase Cloud Function and Firebase Admin SDK or is there a standard way of solving this problem?
It is quite simple. APIs on the user continue to work even if the user is not current.
const anonymousUser = firebase.auth().currentUser;
firebase.auth().currentUser.linkWithPopup(provider)
.then(function (result) {
var token = result.credential.accessToken;
// The signed-in user info.
var user = result.user;
// ...
}).catch(function (error) {
// Handle Errors here.
var errorCode = error.code;
if (errorCode === 'auth/credential-already-in-use') {
return firebase.auth().signInWithCredential(error.credential);
}
}).then((result) => {
if (anonymousUser.uid !== result.user.uid) {
return anonymousUser.delete()
.then(() => {
return result;
});
}
return result;
}).then((result) => {
return dispatch(loadContent(result.user.uid))
}).then(() => {
history.push('/');
});

Categories