Flutter Phone Authentication using Firebase

Muhammad Sabeel Ahmed
3 min readJun 20, 2023

Phone number verification using Firebase in the Flutter Web app can be done by sending OTP SMS to the phone number. The user will enter the OTP in the message and will easily sign in to his/her account. We are going to implement it in Flutter.

Step by Step implementation

Step 1: Create a new Flutter Project
Android Studio:

Open Android Studio -> Go to New Flutter Project -> Select Flutter in the left tab and Flutter SDK Path and go to Next. Specify the project name, project location, and project type as Application, and select preffered platform from Platforms section. Click on Finish. You can see a directory Android, iOS & Web is now created along with all the directories.

VS Code:
Open CMD in any folder and run command “flutter create project_name”
Run command “cd project_name”
Run command “code .”

You can see a directory Android, iOS & Web is now created along with all the directories.

Step 2: Create Project on Firebase
Run command “flutterfire configure”
Select existing project or create new using arrow keys
Enable Phone Authentication from Firebase goto Authentication > Signin Methods > Phone > Enable

Step3: Create a phoneOTPVerification.dart file in the lib directory and refer to the following code.

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';

class PhoneOTPVerification extends StatefulWidget {
const PhoneOTPVerification({Key? key}) : super(key: key);

@override
State<PhoneOTPVerification> createState() => _PhoneOTPVerificationState();
}

class _PhoneOTPVerificationState extends State<PhoneOTPVerification> {
TextEditingController phoneNumber = TextEditingController();
TextEditingController otp = TextEditingController();
bool visible = false;
var temp;

@override
void dispose() {
phoneNumber.dispose();
otp.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Firebase Phone OTP Authentication"),
),
body: SizedBox(
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
inputTextField("Contact Number", phoneNumber, context),
visible ? inputTextField("OTP", otp, context) : SizedBox(),
!visible ? SendOTPButton("Send OTP") : SubmitOTPButton("Submit"),
],
),
),
);
}

Widget SendOTPButton(String text) => ElevatedButton(
onPressed: () async {
setState(() {visible = !visible;});
temp = await FirebaseAuthentication().sendOTP(phoneNumber.text);
},
child: Text(text),
);

Widget SubmitOTPButton(String text) => ElevatedButton(
onPressed: () =>FirebaseAuthentication().authenticate(temp, otp.text),
child: Text(text),
);

Widget inputTextField(String labelText, TextEditingController textEditingController, BuildContext context) =>
Padding(
padding: EdgeInsets.all(10.00),
child: SizedBox(
width: MediaQuery.of(context).size.width / 1.5,
child: TextFormField(
obscureText: labelText == "OTP" ? true : false,
controller: textEditingController,
decoration: InputDecoration(
hintText: labelText,
hintStyle: TextStyle(color: Colors.blue),
filled: true,
fillColor: Colors.blue[100],
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.transparent),
borderRadius: BorderRadius.circular(5.5),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.transparent),
borderRadius: BorderRadius.circular(5.5),
),
),
),
),
);
}

class FirebaseAuthentication {
String phoneNumber = "";

sendOTP(String phoneNumber) async {
this.phoneNumber = phoneNumber;
FirebaseAuth auth = FirebaseAuth.instance;
ConfirmationResult result = await auth.signInWithPhoneNumber(
'+92$phoneNumber',
);
printMessage("OTP Sent to +92 $phoneNumber");
return result;
}

authenticate(ConfirmationResult confirmationResult, String otp) async {
UserCredential userCredential = await confirmationResult.confirm(otp);
userCredential.additionalUserInfo!.isNewUser
? printMessage("Authentication Successful")
: printMessage("User already exists");
}

printMessage(String msg) {
debugPrint(msg);
}
}

Step 4: now put these lines in main.dart file

void main() async {
//Firebase initialization
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);

//Default screen for application
runApp(const MyApp())

}

class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the
// root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter OTP Demo by Sabeel',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: PhoneOTPVerification(),
);
}
}

Step 5: Now run project by using command “flutter run”

--

--

Muhammad Sabeel Ahmed

Experienced in developing Mobile Applications and various scalable solutions capable of handling millions of users.