Firebase provides email templates for most user email such as password reset but doesn't provide one for the email sent via the sendSignInLinkToEmail method.
It is possible to either customise the content of this email or even better simply get generated link and then use your own email delivery system to sent the email?
You can't modify the built-in templates, however you can make use of the Admin SDKs to generate the action links.
This process is documented here.
const destEmail = 'user#example.com';
admin.auth().generateSignInWithEmailLink(destEmail, actionCodeSettings)
.then((link) => {
// Construct sign-in with email link template, embed the link and
// send using custom SMTP server.
return sendSignInEmail(destEmail, displayName, link);
})
.catch((error) => {
// Some error occurred.
});
Related
I'm trying to build an app that authenticate through firebase. During the whole process I found that firebase release in any case a token even if email is not verified.
Because I want firebase give me a token only when email is verified I decided to use firebase-cloud-functions to check through the beforeCreate() function if a user's email was enabled and if not, send an email for verification generating an email link using 'firebase-admin' admin.auth().generateEmailVerificationLink.
According cloud-functions documentation here: https://firebase.google.com/docs/auth/extend-with-blocking-functions#common-scenarios it is possible to configure firebase-admin in cloud function in this way:
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
const locale = context.locale;
if (user.email && !user.emailVerified) {
// Send custom email verification on sign-up.
return admin.auth().generateEmailVerificationLink(user.email).then((link) => {
return sendCustomVerificationEmail(user.email, link, locale);
});
}
});
Apparently this doesn't work!!! In my case when I create a user I receive following error code:
FirebaseAuthError: There is no user record corresponding to the provided identifier.
Doing some other research it seems that to generate the email verification link FirebaseAuth should have already create or authenticate the user.
How is this thing not working since it's in the documentation? Do you have an idea about how this really work? Any example or detail would be great!!!
Thank to all.
I have a Flutter mobile application and I am using Firebase authentication. I have decided to use email template for verifying user email. In the backend, I call generateEmailVerificationLink(email ,actionCode) to create an email verification link, then I pass the link to a good looking email template and send it to the user.
I would like to do the same thing for updating user email. But I am not sure which function to call in the backend to create the proper link that I need to pass to the email temple. The mode in the action code should be "verifyAndChangeEmail"
Does any one know?
I found this link https://firebase.google.com/docs/auth/admin/email-action-links
but it does not say how to generate a link for updating user email. Does that mean that I can't have a custom email for updating user email??
Please help.
You can use the same generateEmailVerificationLink() method, and, in the page opened via the link, you need to trigger, in the back-end, the updateUser() method of the Admin SDK.
More concretely:
In a Cloud Function (or a server you own), generate an email verification link for the new email (as explained in the doc you mention in your question) and build and send an email containing this link (for example by calling a microservice like Sendgrid).
The user receives the email in his mailbox. When he clicks on the link, the user is redirected to a web page you host somewhere (for example with Firebase hosting): the email is then verified, with applyActionCode(), as shown in the code found in this page in the Firebase doc (see "4. Handle email address verification by calling applyActionCode.").
Then, in the .then((resp) => {...}) block of this page, implement a call to a callable Cloud Function in which you use the updateUser() method to update the user's email. In the callable cloud function you must check that the uid (User ID) that you pass to the updateUser() method is the uid of the caller (with const uid = context.auth.uid; see the doc).
I have implemented email verification in my app but i've noticed to email providers have bots that open the link before the user gets to see (thus verifying the email).
is there a way to prevent such behavior? or email verification by code or have action on the screen the user would need to click to verify?
Rather than providing a direct link to Firebase (the default), you can customize your email verification template to direct the user to another location, such as your application, where they must press a button to complete the verification process. Then you can use the Auth.applyActionCode() method with the oobCode that was supplied in the query parameters.
You'll have to process the verifications yourself if you wish to customize it. You can try it by generating email verification link using Admin SDK in a Cloud Function/Server
// Admin SDK API to generate the email verification link.
const useremail = 'user#example.com';
admin
.auth()
.generateEmailVerificationLink(useremail, actionCodeSettings)
.then((link) => {
// Construct email verification template, embed the link and send
// using custom SMTP server.
return sendCustomVerificationEmail(useremail, displayName, link);
})
.catch((error) => {
// Some error occurred.
});
Now that you've sent the email, you'll have to self-host a page to that opens after opening that link.
You can find detailed explanation in the documentation
That being said, you can implement reCaptcha or any verification service you want to use to make sure the user is not a bot and verify it in your custom handler.
I'm using firebase auth in my app and i'm setting up password-less email sign up.
I have managed to set the email from my own domain but how do i change the text sent in the email for magic link?
I can see the configuration for the other template emails but not this one.
The email in question is this one:
Hello,
We received a request to sign in to teamname using this email address. If you want to sign in with your youremail account, click this link: link
If you did not request this link, you can safely ignore this email.
Thanks,
There is no way to edit any of the email templates that Firebase Authentication uses. The reason for this is that this allows bad actors to use Firebase to spam people, which would put the service at risk.
To control what message gets sent, you'll have to send it yourself and handle the verification flow with a custom email action handler. See How to modify Email Confirmation message - Firebase.
You could also take full control of the verification flow, and then use the Admin SDK to set the emailVerified flag of the user's profile.
Following on from Frank's answer, you will have to create your own email action link using the Firebase Admin SDK and then put that link in your custom email which you will then send using whatever service (Sendgrid, Mailgun, etc.).
See how to create the action link here: Generating Email Action Links
the only way to customize your email body is to install firebase extension called Trigger Email but it'll put you on the Blaze plan because it makes requests to third-party APIs, and as they specified on the extension's page you'll only be charged for usage that exceeds Firebase's free tier.
There are two ways to customize the email body when using the Firebase authentication service. However, the drawback is that you will have to create a backend to send the email yourself rather than just using a function from the SDK that handles everything automatically.
Generate email action links:
This is the most efficient method, it requires that you use the Firebase Admin SDK to generate a link that will be embedded in emails sent to your users.
Here is an example code that shows how to create an API to send customized verification emails using Express as the backend:
// Creating a POST route that sends customized verification emails
app.post('/send-custom-verification-email', async (req, res) => {
const {userEmail, redirectUrl} = req.body
const actionCodeSettings = {
url: redirectUrl
}
try{
// generate action like with the Firebase Admin SDK
const actionLink = await getAuth()
.generateEmailVerificationLink(userEmail, actionCodeSettings)
// embedding action link to customized verification email template
const template = await ejs.renderFile('views/verify-email.ejs', {
actionLink
})
// send verification email using SendGrid, Nodemailer, etc.
await sendVerificationEmail(userEmail, template, actionLink)
res.status(200).json({message:'Email successfully sent'})
}catch(error){
// handle errors
}
})
You can read more about it in the article I wrote here
Take full control over the workflow:
With this, the Firebase Admin SDK won't be used to generate an action link, but rather, you will generate the link yourself and create an API that uses the Admin SDK to handle the action to be taken whenever the link is clicked.
To do this you will have to create two API routes. One is a route that sends the emails and the other is a route that uses the Firebase Admin SDK to handle the action to be taken when the link attached to the email is clicked.
I want to implement a reset password form. For that I need to check whether the text input email that user input in out text field is present in our firebase authentication database or not, so that if it is I can send Reset password mail or else show him a pop-dialog to rectify the email.
I've already applied the email checking part where I check wether the text is Email or not.
Firebase Auth can actually manage that for you. Simply call the sendPasswordResetEmail() method like this:
_auth.sendPasswordResetEmail(email: email)
.then((void v) => {
// password reset email sent successfully
})
.catchError((Error error) => {
// There was an error verifying the email
// Check the output of error.toString()
// This is where you may want to show a pop-up dialog
});
If the email is badly formatted or if the email is not present on the Auth Database, the code will always execute the catchError method.