This question already has answers here:
Is there a way to send the verification email with the Firebase Admin SDK from my Node.js server?
(3 answers)
Closed 4 years ago.
I'm trying to send an email verification to users using firebase auth admin. All examples seem to use firebase.auth().currentUser;, however, in my case I am logged in as an admin user viewing a custom dashboard list of users to take action on rather than being logged in as an individual user.
I can successfully change a user record using this approach by passing in the UID to the updateUser method and the changes... e.g.
let userRecord = await fbAuth.updateUser(blogUID, {
email: req.body.BloggerEmail
})
and can retrieve the userdetails of the user I want using:
var userA = await fbAuth.getUser(blogUID)
However, the user object returned by this method does't allow me to call the sendEmailVerification method (it appears getUser doesn't return the same object type as getCurrentUser
try {
var userA = await fbAuth.getUser(blogUID).sendEmailVerification()
console.log("Sent new verification email");
} catch(error) {
console.log("Error sending verification email " + error);
}
[this fails, sendEmailVerification is not a method]
Official Reference Doc I've tried to use:
https://firebase.google.com/docs/auth/web/manage-users#send_a_user_a_verification_email
Appreciate your help.
Since your code uses the Admin SDK to look up a user by their UID, it can only call methods from the Admin SDK. You can't simply match methods from the Admin SDK and the client-side SDKs.
Since the Admin SDK doesn't have a method to send a verification email (see this), you will either have to let the client do this, or implement your own email verification flow. See firebase admin SDK create user and send verification email
Related
So I followed this tutorial on how to sign in a user with rnfirebase and google signup. And it works fine. Here is the code:
const googleSignUp = async () => {
// Get the users ID token
const { idToken } = await GoogleSignin.signIn();
// Create a Google credential with the token
const googleCredential = auth.GoogleAuthProvider.credential(idToken);
// Sign-in the user with the credential
const user = auth().signInWithCredential(googleCredential);
return { idToken, user };
};
(Let me note here, that the app has already a sign in with email and password way, with Firebase).
Then I realized that the user cannot change his name, email or delete his account.
Looking deeper, I found out that the onAuthStateChanged(firebase.auth, async (user) => ... returns null for the user.
I've seen in some older answers that if you use Google sign up, you need to sign up the user with signInWithCredential, which I use, so this in not the issue.
Could it be a problem that for email/password sign in, I use code from Firebase web and not from rnfirebase? Although I already had a combination of those, using the push notifications from rnfirebase.
Can someone explain why I get this behavior, and how to fix it?
Thanks!
If I understand correctly, you use both the react-native-firebase library (which wraps the native iOS and Android SDKs) and the JavaScript Web SDK for Firebase in your app.
If that is the case, both indeed have a separate sign-in state, and signing into one won't fire onAuthStateChanged listeners on the other.
You'll have to pick one SDK to authenticate with Firebase, and then use that for both providers.
My plan is to ONLY sign in a user if the email has been verified. I am using a if-statement to check if the email is verified using the built in "emailVerified" function but it is crashing.
function login(email, password) {
if (email.emailVerified) {
console.log("trying to log user");
return auth.signInWithEmailAndPassword(email, password);
} else {
console.log("failed to log user");
alert("Please verify your email");
return false;
}
}
There is no way to determine whether a profile's emailVerified property is set in the client-side SDK without signing in. So with only the client-side SDK, you won't be able to do what your pseudo-code does.
What you can do is create a custom API in a trusted environment (for example on Cloud Functions) where you use the Admin SDK to get a user profile by its email address and then check if its emailVerified property is set to true. You can then call this custom API from within your application code. But this still won't prevent a malicious user from calling the signInWithEmailAndPassword method themselves
Alternatively, and much simpler, is to sign in first, then check if the email is verified, and only allow the user to continue using the app (and accessing data) if the email is verified.
Note that this topic comes up quite regularly, so I recommend also reading:
Only let pre-verified users log into Firebase
Firebase - Auth - discover users who signed up but not verified email
Firebase Auth - createUserWithEmailAndPassword() - prevent login until email is verified
Can I get updated emailVerified without logging out?
and more from these search results
Right now, I only want users who have already registered and been verified with our software to login, and I have saved the list of emails of users (stripped of special characters) inside Firebase. Currently, when the user logs in, I use the following function to check if their email is in this list:
function isEmailValid(userEmail, trueCallback, falseCallback) {
var emailHash = userEmail.replace(/[^a-zA-Z0-9]/g, "");
firebase
.database()
.ref("validEmails/" + emailHash)
.on("value", snapshot => {
if (snapshot.val()) {
trueCallback(snapshot.val());
} else {
falseCallback();
}
});
}
Although this method works, it is quite unwieldy, as the user is still able to log in initially before the function callback is called, and their email is still shown in the "Authentication" tab in Firebase.
Is there a better way to only allowed pre-verified users to log into Firebase?
I'm pretty sure this has been covered before: there currently is no way to prevent users from signing in with Firebase Authentication. But if you want to prevent them from accessing backend resources, you can check whether their email address is verified either in the server-side security rules (for Realtime Database, Storage, or Firestore), or in your own server-side code.
At I/O a demo was given of upcoming functionality in Cloud Function that would allow you to prevent signing in users without a verified email address. But I don't know when this functionality will available in a public API.
Also see:
Firebase Prevent Creating Account Before Email Verification
How to prevent user authentication in Firebase/Vue.js BEFORE email is verified
How do I lock down Firebase Database to any user from a specific (email) domain?
According to the documentation (https://developers.google.com/identity/one-tap/web/retrieve-credentials), we can get our saved password, just like when we use Credential Management API on Chrome.
I'm already currently logged in to Google in my browser.
I have tried to use the googleyolo api, using .retrieve() function as documented:
const retrievePromise = googleyolo.retrieve({
supportedAuthMethods: [
"https://accounts.google.com",
"googleyolo://id-and-password"
],
supportedIdTokenProviders: [
{
uri: "https://accounts.google.com",
clientId: "*********-**********.apps.googleusercontent.com"
}
]
}).then(res => console.log(res));
and it only return the idToken, no password returned.
But weirdly, when I tried using Credential Management API on Chrome my saved credentials popped up.
The question is,
1. What went wrong?
2. Where did googleyolo get its list of credentials? Because I checked at my https://passwords.google.com, and my credentials exists
3. What should I do/troubleshoot to get my password credentials?
Sorry for the confusion, passwords are only available in browsers that support the Credential Management API (which the library uses to retrieve the passwords). Will update the documentation to clarify that.
Not sure where you get the "googleyolo://id-and-password" from in the supportedAuthMethods argument. In your link, it specifically says only Google is supported.
googleyolo gets a list of users from your current browser. You will get more users if you have multiple users logged into a Google account.
When I implemented Google signon, I simply use the idtoken to confirm the identify of the user. No password is return from calling googleyolo.
Once you confirmed the user's identify, you can use the method provided to signin.
useGoogleIdTokenForAuth(credential.idToken);
I am working in laravel and firebase as a backend for authentication and data storage. I am using firebase provided js code to signin the user
firebase.auth().signInWithEmailAndPassword(email, password).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
The problem is that I want to protect my routes from non-authenticated users. How would I check this in my middleware that user is logged in or not because js stores current user's uid in localStorage. Do I have to use a separate database for this purpose? Please help me to go in right direction.
You have to call:
auth.currentUser.getIdToken().then(function(token) {
// The Firebase id token is returned here.
// You will have to send that along your requests to your server.
// Keep in mind this is a short lived token
// You have to call getToken each time you need it in case
// it is auto refreshed underneath.
});
Currently, Firebase provides node.js and java backend libraries to verify the token (to check the user is logged in).
https://firebase.google.com/docs/auth/server
A php library is in the works. When it is ready, it should provide similar functionality for minting custom tokens and verifying Firebase id tokens.
You can simply use this https://github.com/vinkas0/firebase-auth-laravel laravel package to authenticate via firebase