Email OTP authentication with Firebase in FlutterFlow allows users to securely verify their identity using a one-time password sent to their email. This process involves configuring Firebase for email authentication, generating and sending OTPs, verifying user input, and handling authentication states within FlutterFlow.
FlutterFlow is a low-code development platform built on top of Flutter, Google's open-source UI toolkit for building natively compiled applications for mobile, web, and desktop from a single codebase.
To set up your Flutterflow project, please follow the steps below:
Firebase is a Google platform offering tools to build, improve, and scale apps across mobile, web, and desktop, with services like real-time databases, authentication, and serverless backend solutions.
To set up your Firebase project, please follow the steps below:
Now our flutterflow and firebase projects are setup. Let’s start the to add passwordless functionality in our fluterflow project.
Step 1 : - In flutterflow we have created 3 simple pages :
Step 2 : - Download service account private key.
Project setting → Service accounts → Generate new private key.
Service account private key will be downloaded in your system as a json file, in my case it is downloaded as mytesting-7cae3-firebase-adminsdk-bg0ir-1e888126db.json, which we will use in our cloud function.
Note : - For initial steps to create cloud function, check the below article
https://www.flutterflowdevs.com/blog/how-admin-can-change-password-of-other-authenticate-users
If you have followed the steps in the given article, a functions
folder should have been created on your system. Now, proceed with the steps below
Step 1 : - Open the folder in vs code.
Step 2 : - Add the service account private key ( json file which you already downloaded ) in the same folder(FUNCTIONS). same as we added.
Step 3 : - Create .env file in the same folder.
This file contains an email id and password
GMAIL_EMAIL=your_email_id.com
GMAIL_APP_PASSWORD=your_password
GMAIL_EMAIL : - This id might be from different email providers( yahoo, gmail, outlook, etc). This email id will used to send otp.
GMAIL_APP_PASSWORD : - This is not your email account password, it is a App password.
Important Note About App Passwords for Gmail:
When using Gmail, you need to:
1.
2.
To generate an App Password for Gmail:
Note : - Now you have enabled 2-Step Verification and create App password, so add that password in .env file.
Step 4 : - Install some dependencies in your cloud function.
package.json
"dependencies": {
"dotenv": "^16.4.7",
"firebase-admin": "^12.1.0",
"firebase-functions": "^5.0.0",
"nodemailer": "^6.10.0"
},
Commands to install dependencies :
Step 5 : - Add the below code in index.js file.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const nodemailer = require('nodemailer');
const serviceAccount = require('./mytesting-7cae3-firebase-adminsdk-bg0ir-1e888126db.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
require('dotenv').config();
// For local testing, set up environment variables
const gmailEmail = process.env.GMAIL_EMAIL || 'your-test-email@gmail.com';
const gmailPassword = process.env.GMAIL_APP_PASSWORD || 'your-test-app-password';
// Email configuration
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: gmailEmail,
pass: gmailPassword
}
});
// Function to send OTP email
exports.sendOTPEmail = functions.https.onCall(async (data, context) => {
const { email, otp } = data;
if (!email || !otp) {
throw new functions.https.HttpsError(
'invalid-argument',
'Email and OTP are required'
);
}
console.log(`Sending OTP ${otp} to ${email}`);
const mailOptions = {
from: `Your App <${gmailEmail}>`,
to: email,
subject: 'Your Login Code',
html: `
<div style="font-family: Arial, sans-serif; padding: 20px; text-align: center;">
<h2>Your Login Code</h2>
<p>Use the following code to sign in to your account:</p>
<div style="font-size: 24px; font-weight: bold; letter-spacing: 5px; margin: 20px 0; padding: 10px; background-color: #f0f0f0; border-radius: 5px;">${otp}</div>
<p>This code will expire in 15 minutes.</p>
</div>
`
};
try {
await transporter.sendMail(mailOptions);
console.log('Email sent successfully');
return { success: true };
} catch (error) {
console.error('Error sending email:', error);
throw new functions.https.HttpsError('internal', 'Error sending email');
}
});
exports.generateCustomToken = functions.https.onCall(async (data, context) => {
const { email } = data;
if (!email) {
throw new functions.https.HttpsError(
'invalid-argument',
'Email is required'
);
}
try {
// Check if user exists in Firebase Auth
let uid;
try {
const userRecord = await admin.auth().getUserByEmail(email);
uid = userRecord.uid;
} catch (error) {
// User doesn't exist, create a new user
const newUser = await admin.auth().createUser({
email: email,
emailVerified: true, // Since we verified with OTP, we can set this to true
});
uid = newUser.uid;
// Optionally create initial user data in Firestore
await admin.firestore().collection('users').doc(uid).set({
email: email,
createdAt: admin.firestore.FieldValue.serverTimestamp(),
});
}
// Generate custom token
const token = await admin.auth().createCustomToken(uid);
return { token };
} catch (error) {
console.error('Error generating custom token:', error);
throw new functions.https.HttpsError('internal', 'Error generating authentication token');
}
});
Note : - Add the path of your service account json file.
Step 6 : - Deploy Cloud Function.
Run the command to deploy the project to Firebase:
firebase deploy
After deployment completed, you will get 2 apis for this cloud function.
Method : - POST
Header : - Content-Type:application/json
Body : - {
"data": {
"email": "email",
"otp": "otp"
}
}
**Response**
{
"result": {
"success": true
}
}
Method : - POST
Header : - Content-Type:application/json
Body : - {
"data": {
"email": "email"
}
}
**Response**
{
"result": {
"token": "eyJhbGciOiJSUzI1NiIsInR5----------Custom Token-----"
}
}
import 'dart:math';
Future<String> generateRandomOTP() async {
// Add your function code here!
Random random = Random();
int randomOTP = 10000 + random.nextInt(90000);
return randomOTP.toString();
}
import 'package:firebase_auth/firebase_auth.dart';
Future signInOrCreateUser(String token) async {
// Add your function code here!
return await FirebaseAuth.instance.signInWithCustomToken(token);
}
Follow the below steps to implement Apis and Custom function functionality in Flutterflow
Step 1 : - In Auth Page, Send Otp button action flow
Step 2 : - In Otp Page, Submit button action flow.
Implementing Email OTP authentication in FlutterFlow using Firebase enhances security by allowing passwordless sign-ins. This guide covered setting up a FlutterFlow project, integrating Firebase authentication, and configuring a cloud function to generate and verify OTPs. By leveraging Firebase's authentication features and custom actions, users can seamlessly log in with a one-time password sent to their email. Deploying cloud functions ensures secure email verification and token generation, making the authentication process efficient and user-friendly.