Firebase Email verification not working with ActionCodeSetting - firebase

I'm trying to implement verification of a user's email (with the default verification URL in the email template), AND an ActionCodeSetting URL (dynamic link) to bring the user back to the app. I'm baffled by how Firebase's email verification with ActionCodeSetting is supposed to work. I have read every available page of documentation and it is still unclear to me how to properly configure the "continue URL" to NOT preempt and override the default verification URL.
What I have done:
I tested the email verification with the automatically generated email verification link. It worked.
I then added an ActionCodeSetting URL that uses a domain that is added to the Associated Domains of the XCode project. This worked to bring the user back to the app after clicking the verification link.
Problem: the email verification no longer works.
Here is the code I have implemented:
var actionCodeSettings = ActionCodeSettings.init()
actionCodeSettings.handleCodeInApp = true
let user = Auth.auth().currentUser
let urlString = "https://blaproject.page.link/zCB4"
actionCodeSettings.setIOSBundleID(Bundle.main.bundleIdentifier!)
actionCodeSettings.setAndroidPackageName("com.example.android", installIfNotAvailable:true, minimumVersion:"12")
Auth.auth().currentUser?.sendEmailVerification(with: actionCodeSettings, completion: { (error) in
print("verification email sent")
print("action code setting URL is: \(String(describing: actionCodeSettings.url))")
})
Here is the default verification URL from the email template in the Firebase console:
https://blaproject-ea9d6.firebaseapp.com/__/auth/action?mode=&oobCode=
And here is the verification URL that gets sent by the above code:
https://blaproject.page.link?link=https://blaproject-ea9d6.firebaseapp.com//auth/action?apiKey%3DAIzaSyAi1fxd-HdkfXzYJxTpwmB3_mVCy5gvWxA%26mode%3DverifyEmail%26oobCode%3DqjvGoqc1n3ya0OIi_tWIYTpp59DYKgB6Sbj0EymN2IkAAAFkYNutMA%26continueUrl%3Dhttps://blaproject.page.link/zCE4%26lang%3Den&apn=com.example.android&amv=12&ibi=blaproject.blaprojectV0-2&ifl=https://blaproject-ea9d6.firebaseapp.com//auth/action?apiKey%3DAIzaSyAi1fxd-HdkfXzYJxTpwmB3_mVCy5gvWxA%26mode%3DverifyEmail%26oobCode%3DqjvGoqc1n3ya0OIi_tWIYTpp59DYKgB6Sbj0EymN2IkAAAFkYNutMA%26continueUrl%3Dhttps://blaproject.page.link/zCE4%26lang%3Den
So my question is, why does this URL not verify the user's email and then use the continue URL (and the associated domain) to trigger the app to open? It only triggers the app to open, without verifying the user's email.
Thanks for any tips you can provide to help me understand what I'm not understanding :)

When the link triggers your app to open. You need to parse the oobCode from the deep link. You can use FDL client library to get the deep link. Refer to the following documentation on the format of the deep link and how to parse the code: https://firebase.google.com/docs/auth/custom-email-handler
Once you get the code, you need to apply it using the auth.applyActionCode(code) API. This will verify the email.
After verification, you can call user.reload() to update the emailVerified property on the user. You can also force user.getIdToken(true) to force refresh the token with the updated verified email if you are using Firebase security rule.

For get correct 'oobCode', when you handle the URL in the App, make sure, that you are decoding URL from UTF-8. Because it has other symbols in the URL query.
Example how to encode: url.absoluteString.removingPercentEncoding

Related

Firebase SendEmailVerification in Xamarin : how to handle this in App?

I am trying to use email verification in my Xamarin/Firebase app.
I currently have:
using (var actionCode = ActionCodeSettings.NewBuilder()
.SetHandleCodeInApp(true).Build()) {
await user.SendEmailVerification(actionCode);
}
This properly sends a verification email.
What I don't know is how to specify a callback in the app to catch user clicking on the verification link.
Any advice/guidance will be appreciated.
It's still unclear to me what's the point of the SetHandleCodeInnApp option. It seems to indicate that there is a way of handling the verification event in the app
Whether the email action link will be opened in a mobile app or a web link first. The default is false. When set to true, the action code link will be be sent as a Universal Link or Android App Link and will be opened by the app if installed. In the false case, the code will be sent to the web widget first and then on continue will redirect to the app if installed.
For more details, you could check the document. https://firebase.google.com/docs/auth/android/passing-state-in-email-actions

Update email with a custom email template in Firebase

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).

firebase emails verified by link checker bots

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.

Customized email verification success page using Firebase

I am generating email verification using the default Firebase function.
The default email verification success page looks like that:
I want to customize the response page after successful email verification.
Is there a way to do that?
I want to customize the response page after successful email
verification. Is there a way to do that?
Yes, as Frank indicated in his above comment, it is possible and the documentation he refers to explains the mechanism.
As explained in this doc (and also in my other answer :-) ), you need to build a web page in which you will:
Get the values passed as QueryString parameters (e.g. mode or oobCode)
Call, from this web page, the applyActionCode() method of the Firebase JavaScript SDK, passing the values of these parameters to the method.
Upon successful verification, do something, like redirect the user to your app login page.
What's important to note is that you have two ways to generate the email sent to the user (which contains the link to the page described above):
1. Rely on the default Firebase mail mechanism. In order to customize the URL of the verification link (e.g. you want to redirect to https://www.myrapp.com/emailVerifyScreen) you need to change the base URL as shown in the below image ("Customize action URL"). Also explained here in the doc.
2. Send the email through a Cloud Function (or through a server you own). In this case you need to:
a/ Call the generateEmailVerificationLink() method of the Admin SDK, which returns a link
b/ Generate an email containing this link
c/ Send the email to the user (via an SMTP server you control or via a microservice like Mailjet or Sendgrid)
You may have a look at these other answers:
https://stackoverflow.com/a/66350538/3371862
Flutter: Sending Email Verification code through FlutterFire?
How to sign up only the users who have verified thier email addresses using the email link in Firebase javascript?

Firebase custom verification email

I read some other posts about this topic but couldn't finally figure out how to accomplish this.
I want to send the email-verification email normally send from firebase itself from my own email-provider (like mailjet e. g.) The reason is that I want to customize the email text etc.
I also read about creating a custom email handler which I would do too. But this just handles the action that happens when the user clicks on the link in the email.
At the moment I call this from my flutter app after the users sign up:
user.sendEmailVerification();
this makes firebase send the standard verification email to the user. Instead of doing that I'd need to send the email myself. But like seen here I need to have this oobCode generated. to generate a correct link to handle. I just can't find an example on how to do that. What would be the right approach to send the email myself? Maybe I just did not find the right resource. Thanks a lot.
You need to generate and send the email via a backend, by using the Admin SDK. The easiest is to use a Cloud Function, from which you use the Mailjet NodeJS API wrapper.
So, in the Cloud Function, you need to:
Call the generateEmailVerificationLink() method of the Admin SDK, which returns a link
Generate an email containing this link
Send the email to the user (see the Mailjet NodeJS API wrapper documentation)
The first steps are detailed here in the doc.
In order to customize the URL of the verification link (e.g. you want to redirect to https://www.myrapp.com/emailVerifyScreen) you need to change the base URL as shown in the below image ("Customize action URL"). Also explained here in the doc.
Then, when the user clicks on the link in the email he/she has received, you need to do what is explained in the doc you referred to in your question: Create custom email action handlers. See the point #4 "Handle email address verification by calling applyActionCode".
Concretely, in the page of your app https://www.myrapp.com/emailVerifyScreen, you get the query string values from the URL (e.g. var actionCode = getParameterByName('oobCode');) and you use these values to call the applyActionCode(actionCode) method. When the promise returned by this method is fullfilled, you know that the email has been verified.
var actionCode = getParameterByName('oobCode');
auth.applyActionCode(actionCode).then((resp) => {
// Email address has been verified.
// TODO: Display a confirmation message to the user.
// You could also provide the user with a link back to the app.
// TODO: If a continue URL is available, display a button which on
// click redirects the user back to the app via continueUrl with
// additional state determined from that URL's parameters.
}).catch((error) => {
// Code is invalid or expired. Ask the user to verify their email address
// again.
});
One last point to note: you cannot directly get the oobCode alone. The generateEmailVerificationLink() method generates the full URL.
The answer mentioned above is absolutely correct , I am just adding to that how you can create action url in two ways for testing and then deployment way.
1> for custom email action handler you would have to create your own handlers (using HTML and js , react app , flutter anything you want) after doing that you can either test your handler by routing traffic to it (localhost) using ngrok(that will provide you with https url to route traffic on localhost, preferred method for testing) , or you can deploy it and directly use that url . now with that url go to firebase(your project) -> authentication -> templates -> use whatever handler you want( example reset password or email verification) -> edit and add custom action url to route traffic to your handler( hosted(deployed) or local(ngrok routing) .

Resources