Code is copied!
How To Create a OTP Authentication App Using Flutter
In this project, we're excited to present our "Otp authentication" app, developed using Flutter. Our project will guide you through the creation of this engaging Otp authentication app using Flutter. You'll learn how to build an intuitive and responsive user interface. Let's start...
Source Code for the main.dart file
Add the following Code inside your main.dart file :
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'home_page.dart';
void main() async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Home(),
);
}
}
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'home_page.dart';
void main() async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Home(),
);
}
}
Source Code for the home_page.dart file
Add the following Code inside your home_page.dart file :
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'done.dart';
import 'numeric_pad.dart';
class Home extends StatefulWidget {
const Home({super.key});
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home>
{
TextEditingController _codecontroller = new TextEditingController();
String phoneNumber = "", data = "";
final FirebaseAuth _auth = FirebaseAuth.instance;
String smscode = "";
_signInWithMobileNumber() async {
try {
await _auth.verifyPhoneNumber(
phoneNumber: '+91' + data.trim(),
verificationCompleted: (PhoneAuthCredential authCredential) async {
await _auth.signInWithCredential(authCredential).then((value) {
Navigator.push(
context, MaterialPageRoute(builder: (context) => Done()));
});
},
verificationFailed: ((error)
{
print(error);
}),
codeSent: (String verificationId, [int? forceResendingToken]) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
title: Text("Enter OTP"),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: _codecontroller,
)
],
),
actions: [
ElevatedButton(
onPressed: () {
FirebaseAuth auth = FirebaseAuth.instance;
smscode = _codecontroller.text;
PhoneAuthCredential _credential =
PhoneAuthProvider.credential(
verificationId: verificationId,
smsCode: smscode);
auth.signInWithCredential(_credential)
.then((result) {
if (result != null) {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Done()));
}
}).catchError((e) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Error Occured'),
content: Text('Please check and enter the correct verification code'), // Format total price with two decimal places
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('Close'),
),
],
);
},
);
// print(e);
});
},
child: Text("Done"))
],
));
},
codeAutoRetrievalTimeout: (String verificationId) {
verificationId = verificationId;
},
timeout: Duration(seconds: 45));
} catch (e) {
print(e);
}
}
@override
Widget build(BuildContext context) {
return
Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text(
"Continue with phone",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
backgroundColor: Colors.white,
elevation: 0,
centerTitle: true,
),
body: SafeArea(
child: Column(
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFFFFFFFF),
Color(0xFFF7F7F7),
],
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 150,
child: Image.asset('images/holding-phone.png'),
),
Padding(
padding:
EdgeInsets.symmetric(vertical: 14, horizontal: 64),
child: Text(
"You'll receive a 6 digit code to verify next.",
style: TextStyle(
fontSize: 20,
color: Color(0xFF818181),
),
),
),
],
),
),
),
Container(
height: MediaQuery.of(context).size.height * 0.13,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(25),
),
),
child: Padding(
padding: EdgeInsets.all(16),
child: Row(
children: [
Container(
width: 230,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Enter your phone",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.grey,
),
),
SizedBox(
height: 8,
),
Text(
phoneNumber,
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
],
),
),
Expanded(
child: GestureDetector(
onTap: () {
data = phoneNumber;
phoneNumber = "";
setState(() {
});
_signInWithMobileNumber();
},
child: Container(
decoration: BoxDecoration(
color: Color(0xFFFFDC3D),
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
child: Center(
child: Text(
"Continue",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
),
),
),
],
),
),
),
NumericPad(
onNumberSelected: (value) {
setState(() {
if (value != -1) {
phoneNumber = phoneNumber + value.toString();
}
else
{
phoneNumber =
phoneNumber.substring(0, phoneNumber.length - 1);
}
});
},
),
],
),
),
);
}
}
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'done.dart';
import 'numeric_pad.dart';
class Home extends StatefulWidget {
const Home({super.key});
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home>
{
TextEditingController _codecontroller = new TextEditingController();
String phoneNumber = "", data = "";
final FirebaseAuth _auth = FirebaseAuth.instance;
String smscode = "";
_signInWithMobileNumber() async {
try {
await _auth.verifyPhoneNumber(
phoneNumber: '+91' + data.trim(),
verificationCompleted: (PhoneAuthCredential authCredential) async {
await _auth.signInWithCredential(authCredential).then((value) {
Navigator.push(
context, MaterialPageRoute(builder: (context) => Done()));
});
},
verificationFailed: ((error)
{
print(error);
}),
codeSent: (String verificationId, [int? forceResendingToken]) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
title: Text("Enter OTP"),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: _codecontroller,
)
],
),
actions: [
ElevatedButton(
onPressed: () {
FirebaseAuth auth = FirebaseAuth.instance;
smscode = _codecontroller.text;
PhoneAuthCredential _credential =
PhoneAuthProvider.credential(
verificationId: verificationId,
smsCode: smscode);
auth.signInWithCredential(_credential)
.then((result) {
if (result != null) {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Done()));
}
}).catchError((e) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Error Occured'),
content: Text('Please check and enter the correct verification code'), // Format total price with two decimal places
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('Close'),
),
],
);
},
);
// print(e);
});
},
child: Text("Done"))
],
));
},
codeAutoRetrievalTimeout: (String verificationId) {
verificationId = verificationId;
},
timeout: Duration(seconds: 45));
} catch (e) {
print(e);
}
}
@override
Widget build(BuildContext context) {
return
Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text(
"Continue with phone",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
backgroundColor: Colors.white,
elevation: 0,
centerTitle: true,
),
body: SafeArea(
child: Column(
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFFFFFFFF),
Color(0xFFF7F7F7),
],
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 150,
child: Image.asset('images/holding-phone.png'),
),
Padding(
padding:
EdgeInsets.symmetric(vertical: 14, horizontal: 64),
child: Text(
"You'll receive a 6 digit code to verify next.",
style: TextStyle(
fontSize: 20,
color: Color(0xFF818181),
),
),
),
],
),
),
),
Container(
height: MediaQuery.of(context).size.height * 0.13,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(25),
),
),
child: Padding(
padding: EdgeInsets.all(16),
child: Row(
children: [
Container(
width: 230,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Enter your phone",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.grey,
),
),
SizedBox(
height: 8,
),
Text(
phoneNumber,
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
],
),
),
Expanded(
child: GestureDetector(
onTap: () {
data = phoneNumber;
phoneNumber = "";
setState(() {
});
_signInWithMobileNumber();
},
child: Container(
decoration: BoxDecoration(
color: Color(0xFFFFDC3D),
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
child: Center(
child: Text(
"Continue",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
),
),
),
],
),
),
),
NumericPad(
onNumberSelected: (value) {
setState(() {
if (value != -1) {
phoneNumber = phoneNumber + value.toString();
}
else
{
phoneNumber =
phoneNumber.substring(0, phoneNumber.length - 1);
}
});
},
),
],
),
),
);
}
}
Source Code for the numeric_pad.dart file
Add the following Code inside your numeric_pad.dart file :
import 'package:flutter/material.dart';
class NumericPad extends StatelessWidget {
final Function(int) onNumberSelected;
NumericPad({required this.onNumberSelected});
@override
Widget build(BuildContext context) {
return Container(
color: Color(0xFFF5F4F9),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
height: MediaQuery.of(context).size.height * 0.10,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildNumber(1),
buildNumber(2),
buildNumber(3),
],
),
),
Container(
height: MediaQuery.of(context).size.height * 0.10,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildNumber(4),
buildNumber(5),
buildNumber(6),
],
),
),
Container(
height: MediaQuery.of(context).size.height * 0.10,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildNumber(7),
buildNumber(8),
buildNumber(9),
],
),
),
Container(
height: MediaQuery.of(context).size.height * 0.10,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildEmptySpace(),
buildNumber(0),
buildBackspace(),
],
),
),
],
),
);
}
Widget buildNumber(int number) {
return Expanded(
child: GestureDetector(
onTap: () {
onNumberSelected(number);
},
child: Padding(
padding: EdgeInsets.all(10),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
child: Center(
child: Text(
number.toString(),
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Color(0xFF1F1F1F),
),
),
),
),
),
),
);
}
Widget buildBackspace() {
return Expanded(
child: GestureDetector(
onTap: () {
onNumberSelected(-1);
},
child: Padding(
padding: EdgeInsets.all(10),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
child: Center(
child: Icon(
Icons.backspace,
size: 28,
color: Color(0xFF1F1F1F),
),
),
),
),
),
);
}
Widget buildEmptySpace() {
return Expanded(
child: Container(),
);
}
}
import 'package:flutter/material.dart';
class NumericPad extends StatelessWidget {
final Function(int) onNumberSelected;
NumericPad({required this.onNumberSelected});
@override
Widget build(BuildContext context) {
return Container(
color: Color(0xFFF5F4F9),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
height: MediaQuery.of(context).size.height * 0.10,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildNumber(1),
buildNumber(2),
buildNumber(3),
],
),
),
Container(
height: MediaQuery.of(context).size.height * 0.10,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildNumber(4),
buildNumber(5),
buildNumber(6),
],
),
),
Container(
height: MediaQuery.of(context).size.height * 0.10,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildNumber(7),
buildNumber(8),
buildNumber(9),
],
),
),
Container(
height: MediaQuery.of(context).size.height * 0.10,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildEmptySpace(),
buildNumber(0),
buildBackspace(),
],
),
),
],
),
);
}
Widget buildNumber(int number) {
return Expanded(
child: GestureDetector(
onTap: () {
onNumberSelected(number);
},
child: Padding(
padding: EdgeInsets.all(10),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
child: Center(
child: Text(
number.toString(),
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Color(0xFF1F1F1F),
),
),
),
),
),
),
);
}
Widget buildBackspace() {
return Expanded(
child: GestureDetector(
onTap: () {
onNumberSelected(-1);
},
child: Padding(
padding: EdgeInsets.all(10),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
child: Center(
child: Icon(
Icons.backspace,
size: 28,
color: Color(0xFF1F1F1F),
),
),
),
),
),
);
}
Widget buildEmptySpace() {
return Expanded(
child: Container(),
);
}
}
Source Code for the done.dart file
Add the following Code inside your done.dart file :
import 'package:flutter/material.dart';
class Done extends StatefulWidget {
const Done({super.key});
@override
State<Done> createState() => _DoneState();
}
class _DoneState extends State<Done> {
@override
Widget build(BuildContext context) {
return
Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.white,
elevation: 0,),
body: Center(
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Container(
child: Image.asset('images/verify.webp',
height: 300,),
),
SizedBox(
height: 40,
),
Text('Phone Number Verified',
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
color: Colors.green
),)
],
),
),
),
);
}
}
import 'package:flutter/material.dart';
class Done extends StatefulWidget {
const Done({super.key});
@override
State<Done> createState() => _DoneState();
}
class _DoneState extends State<Done> {
@override
Widget build(BuildContext context) {
return
Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.white,
elevation: 0,),
body: Center(
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Container(
child: Image.asset('images/verify.webp',
height: 300,),
),
SizedBox(
height: 40,
),
Text('Phone Number Verified',
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
color: Colors.green
),)
],
),
),
),
);
}
}