firebase-ui for email verification - javascript

I've set up Firebase email/password authentication successfully using firebase-ui.
var uiConfig = {
signInSuccessUrl: '<?php echo $url; ?>',
signInOptions: [
// Leave the lines as is for the providers you want to offer your users.
firebase.auth.GoogleAuthProvider.PROVIDER_ID,
firebase.auth.FacebookAuthProvider.PROVIDER_ID,
firebase.auth.EmailAuthProvider.PROVIDER_ID
],
// Terms of service url.
tosUrl: '<your-tos-url>'
};
// Initialize the FirebaseUI Widget using Firebase.
var ui = new firebaseui.auth.AuthUI(firebase.auth());
// The start method will wait until the DOM is loaded.
ui.start('#firebaseui-auth-container', uiConfig);
but for security reasons I want the user to confirm her/his email.But fromthe above code it doesn't send a verfication mail to user.
So I've used following method to send a verification mail to user if he/she not verified his/her account mail.
firebase.auth().onAuthStateChanged(function(user) {
if (user && user.uid != currentUid) {
if (firebase.auth().currentUser.emailVerified) {
currentUid = user.uid;
else {
//---- HERE YOU SEND THE EMAIL
firebase.auth().currentUser.sendEmailVerification();
}
But when I used this code it sends multiple verification mails for same account. Which means this method runs each time a user reload the page. It would be really greatful if someone could help me to identify whether verification mail sent or not for a specific user using firebase.

I found what seems to be a better answer to this barely-documented (for JavaScript) Firebase issue in the sample code here:
// FirebaseUI config.
var uiConfig = {
callbacks: {
signInSuccessWithAuthResult: function(authResult, redirectUrl) {
var user = authResult.user;
...
if (authResult.additionalUserInfo.isNewUser)
{
console.log("new signin");
user.sendEmailVerification();
}
...
return true;
},
enjoy!

I'm late but if someone finds it like me:
if(currentUser.metadata.creationTime === currentUser.metadata.lastSignInTime)
Is true when it is a new user, so you have to send the verification email.
You can also do it within signInSuccess, no need to look on onAuthStateChanged

You could use SignInSuccessWithAuthResult callback to send email verification. What you need to do is provide a callback function and check if the user has verified email, if not, sendEmailVerification.

Related

Firebase auth: Update (not signed in user) password without use 'sendPasswordResetEmail'

I know how to update the password of signed in user in firebase auth:
var user = firebase.auth().currentUser; //get current connected user
return user.updatePassword(newPass)
.then(
() => //success
)
.catch(error => this.handleError(error))
}
But I don't know how to do the same with a not signed in user. Perhaps retrieve user auth persistance only with his email with kind like that (but there is no way to do that):
var user = firebase.auth().getUserByEmail(email); //not implmented in auth firebase
PS: I don't want to use the method sendPasswordResetEmail()
var auth = firebase.auth();
return auth.sendPasswordResetEmail(email);
Greatly appreciated help,
Thanks !
The client-side Firebase SDKs only allow sending password reset (and other messages) to the currently signed in user, as any other calls would be major abuse vectors. So there is no way to send a password reset message to a user based on their email address alone.
If you want this functionality, you will have to implement it yourself. At the end of the process, you can then use the Firebase Admin SDK to update the password in the user's profile.
Also see:
Firebase : How to send a password reset email backend with NodeJs
Send Firebase Reset Password Email After Account Created On Server/Admin

Getting Uncaught TypeError in Firebase Auth get current user email

I am trying to get the email of the currently signed in user in my Firebase app, but it keeps giving me an error.
This is my code for getting the current user email:
user_email = firebase.auth().currentUser.email
The error that I get is:
Error Image
It looks like firebase.auth().currentUser is null at the time when your firebase.auth().currentUser.email runs. This is quite common, as Firebase refreshes the user's authentication state when the page loads, and this requires it to make an asynchronous call to the server.
For this reason, you should not assume there is a user signed in. You should either put a check around your current code:
if (firebase.auth().currentUser) {
user_email = firebase.auth().currentUser.email
}
Or (and often better) you should use a so-called auth state listener, to have your code automatically respond to changes in the user's authentication state. From the Firebase documentation on getting the currently signed-in user, that'd be:
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// User is signed in, see docs for a list of available properties
// https://firebase.google.com/docs/reference/js/firebase.User
var uid = user.uid;
user_email = firebase.auth().currentUser.email;
// TODO: execute code that needs `user_email`
} else {
// User is signed out
// ...
}
});

Check if an email already exists in firestore auth on signup (Angular)

As a user signs up to our app, I want them to know whether the email they are trying to sign up with already exists, without having to submit the form (A.K.A on blur of the email field). As it stands, the user has to enter their details and click signup before it let's them know whether the email is taken or not.
The required behaviour can be observed with spotify signup where you enter the email, and as soon as you click away you see the following:
So far, I have written a cloud function (http) that is triggered on blur that calls the getUserByEmail function from firestore admin auth. The function is as follows:
export const checkUserEmail = https.onRequest((req, res) => {
corsHandler(req, res, async () => {
try {
const email = req.body.email;
await admin.auth().getUserByEmail(email);
res.send({status: 200});
return;
} catch(e) {
return Helpers._handleError(res, 400, e.message);
}
})
});
This does work as I can now check at this moment whether or not an email exists, however the problem is it takes anywhere between 3-10 seconds to validate (long enough for the user to get deeper into the signup process).
Is there a way to either:
Speed up the cloud function or
Validate whether a user has already authenticated with the email provided directly on the client side with firestore?
Thanks in advance
You can use a users collection, which you may be doing already. This can store user information and often proves to be really handle since the auth user can't be updated with fields it doesn't how out of the box.
You can store users' emails here and check the collection for the user's input compared to the email field of the users collection here.

Add Google authentication to Firebase Real Time Database

I'm using the Firebase Real Time Database and I need to add user authentication to it. Users can only login with Google as a provider.
Current database mode:
{
"rules": {
".read": true,
".write": true
}
}
New mode should be like this:
// These rules grant access to a node matching the authenticated
// user's ID from the Firebase auth token
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}
What should I use to authenticate in my case? userID, Google providerID or a token like described here?
This is the function without authentication to store data:
createMeetup ({commit, getters}, payload) {
console.log('index.js -> createMeetup')
const meetup = {
title: payload.title,
}
let imageUrl
let key
firebase.database().ref('meetups').push(meetup)
.then((data) => {
key = data.key
return key
})
.then(() => {
commit('createMeetup', {
...meetup,
imageUrl: imageUrl,
id: key
})
})
.catch((error) => {
console.log(error)
})
},
For your use case it seems like you need to sort out a few steps. I'm guessing your application can already connect/use Firebase, but these are essentially it:
Step 1 - Connecting
Connect to Firebase using your API key/config as per usual, should look something like the following.
firebase.initializeApp(config)
See also: https://firebase.google.com/docs/web/setup
You probably already have this somewhere. This does not change, but if you would apply the rules as described your users would not be able to use Firebase after just connecting.
Step 2 - Authenticating
This is basically telling Firebase who is connected. This must be done with a token/method Firebase can verify. Using a Google ID is the most common method.
With an existing Google ID / user login
// Initialize a generate OAuth provider with a `google.com` providerId.
var provider = new firebase.auth.OAuthProvider('google.com');
var credential = provider.credential(googleUser.getAuthResponse().id_token);
firebase.auth().signInWithCredential(credential)
See also: https://firebase.google.com/docs/reference/js/firebase.auth.OAuthProvider#credential
Or make Firebase SDK do the login flow
var provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider).then(function(result) {
// This gives you a Google Access Token. You can use it to access the Google API.
var token = result.credential.accessToken;
// The signed-in user info.
var user = result.user;
// ...
})
See also: https://firebase.google.com/docs/auth/web/google-signin
This last option is preferred / suggested by the documentation you referenced.
If, as you described, users can already login with Google to your app for other functionalities then you should already have a login flow somewhere. Depending on your situation it might be advisable to let the Firebase SDK / library take over this process for simplicity in your application.
Step 3 - Using the database
Lastly, after authenticating users and applying the rules you suggested you will need to also make sure the paths you write to are within those accessible by the current user. You can put this in a simple function to make it easier.
const getUserRef = (ref) => {
const user = firebase.auth().currentUser;
return firebase.database().ref(`/users/${user.uid}/${ref}/`);
}
You should of course not be retrieving the current user every time you want to get a database reference, but I think this clearly illustrates the steps that need to be taken.
You can allow users to login/auth using multiple methods. Then you can merge them together to a single account as described here:
https://firebase.google.com/docs/auth/web/account-linking
So really it boils down to two options:
Allow users to login with multiple methods such as Facebook, Google, Github, basic username/password, etc.
Or allow only a single login method such as Google only.
Whichever options you pick will help you decide which ID to use.
The auth rules in your question are only stating that the users can read/write their own (presumably) user data.
I assume that you are rather looking for a solution to authorize the user to create meetup data and you should crerate rules similar to this:
These rules allow any user that is logged in to create meetups
{
"rules": {
"meetups": {
"$meetupId": {
".read": "auth.uid != null",
".write": "auth.uid != null"
}
}
}
}
Your code-snippet that pushes new meetup data to the database will automatically try and succeed or fail depending on whether the user was logged in or not. You don't need to specifically tell Firebase in which way the user was logged in. Firebase SDK will take care of the authentication for you.
But if you do want to provide different mechanisms depending on which login type that the user is authenticated with, you can check it in the rules. For example if you want to make sure that the user is not just "anonymously" logged in.
See the documentation: https://firebase.google.com/docs/database/security/user-security#section-variable
the documentation has you covered there: Authenticate Using Google Sign-In with JavaScript.
You can let your users authenticate with Firebase using their Google Accounts by integrating Google Sign-In into your app. You can integrate Google Sign-In either by using the Firebase SDK to carry out the sign-in flow, or by carrying out the Google Sign-In flow manually and passing the resulting ID token to Firebase.
Before you begin:
Add Firebase to your JavaScript project.
Enable Google Sign-In in the Firebase console:
In the Firebase console, open the Auth section.
On the Sign in method tab, enable the Google sign-in method and click Save.
Handle the sign-in flow with the Firebase SDK
If you are building a web app, the easiest way to authenticate your users with
Firebase using their Google Accounts is to handle the sign-in flow with the
Firebase JavaScript SDK. (If you want to authenticate a user in Node.js or
other non-browser environment, you must handle the sign-in flow manually.)
To handle the sign-in flow with the Firebase JavaScript SDK, follow these steps:
Create an instance of the Google provider object:
var provider = new firebase.auth.GoogleAuthProvider();
Optional: Specify additional OAuth 2.0 scopes that you want to request from the authentication provider. To add a scope, call addScope().
For example:
provider.addScope('https://www.googleapis.com/auth/contacts.readonly');
See the authentication provider documentation.
Optional: To localize the provider's OAuth flow to the user's preferred language without explicitly passing the relevant custom OAuth parameters, update the language code on the Auth instance before starting the OAuth flow.
For example:
firebase.auth().languageCode = 'pt';
// To apply the default browser preference instead of explicitly setting it.
// firebase.auth().useDeviceLanguage();
Optional: Specify additional custom OAuth provider parameters that you want to send with the OAuth request. To add a custom parameter, call setCustomParameters on the initialized provider with an object containing the key as specified by the OAuth provider documentation and the corresponding value.
For example:
provider.setCustomParameters({
'login_hint': 'user#example.com'
});
Reserved required OAuth parameters are not allowed and will be ignored. See the authentication provider reference for more details.
Authenticate with Firebase using the Google provider object. You can prompt your users to sign in with their Google Accounts either by opening a pop-up window or by redirecting to the sign-in page. The redirect method is preferred on mobile devices.
To sign in with a pop-up window, call signInWithPopup:
firebase.auth().signInWithPopup(provider).then(function(result) {
// This gives you a Google Access Token. You can use it to access the Google API.
var token = result.credential.accessToken;
// The signed-in user info.
var user = result.user;
// ...
}).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
});
Also notice that you can retrieve the Google provider's OAuth token which can be used to fetch additional data using the Google APIs.
This is also where you can catch and handle errors. For a list of error codes have a look at the Auth Reference Docs.
To sign in by redirecting to the sign-in page, call signInWithRedirect:
firebase.auth().signInWithRedirect(provider);
Then, you can also retrieve the Google provider's OAuth token by calling getRedirectResult() when your page loads:
firebase.auth().getRedirectResult().then(function(result) {
if (result.credential) {
// This gives you a Google Access Token. You can use it to access the Google API.
var token = result.credential.accessToken;
// ...
}
// The signed-in user info.
var user = result.user;
}).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
});

Firebase how to verify an email address

I am using Ionic 2 and Firebase to Authenticate my users.
I want to make use of Firebase to Verify a users Email. Much the same way as resetting a password works here:
resetPassword(email: string, fireAuth: firebase.auth.Auth): any {
return fireAuth.sendPasswordResetEmail(email);
}
This emails a link to a user, which allows them to rest their password.
Once a user registers:
fireAuth.createUserWithEmailAndPassword(email, password).then((newUser) => {
this.userProfile.child(newUser.uid).set({ email: email });
});
The new user has the following as expected:
emailVerified:false
I would like to call a Firebase function to email a verification link to the user, once they are verified, I can then allow them to login.
Any help appreciated.

Categories