Nếu đã nâng cấp lên tính năng Xác thực Firebase bằng Identity Platform, bạn có thể thêm tính năng xác thực đa yếu tố qua SMS vào ứng dụng Flutter.
Phương thức xác thực đa yếu tố (MFA) giúp tăng cường bảo mật cho ứng dụng của bạn. Mặc dù kẻ tấn công thường xâm phạm mật khẩu và tài khoản mạng xã hội, nhưng việc chặn tin nhắn văn bản sẽ khó khăn hơn.
Trước khi bắt đầu
Bật ít nhất một nhà cung cấp hỗ trợ tính năng xác thực đa yếu tố. Mọi nhà cung cấp đều hỗ trợ tính năng xác thực đa yếu tố, ngoại trừ tính năng xác thực qua điện thoại, xác thực ẩn danh và Apple Game Center.
Đảm bảo ứng dụng của bạn đang xác minh email của người dùng. Phương thức xác thực đa yếu tố yêu cầu xác minh qua email. Điều này giúp ngăn chặn các đối tượng độc hại đăng ký dịch vụ bằng email mà họ không sở hữu, sau đó khoá chủ sở hữu thực sự bằng cách thêm một yếu tố thứ hai.
Android: Nếu bạn chưa đặt hàm băm SHA-256 của ứng dụng trong bảng điều khiển Firebase, hãy làm như vậy. Hãy xem phần Xác thực ứng dụng để biết thông tin về cách tìm hàm băm SHA-256 của ứng dụng.
iOS: Trong Xcode, hãy bật thông báo đẩy cho dự án của bạn và đảm bảo rằng khoá xác thực APNs của bạn được định cấu hình bằng Giải pháp gửi thông báo qua đám mây của Firebase (FCM). Ngoài ra, bạn phải bật chế độ nền cho thông báo từ xa. Để xem nội dung giải thích chi tiết về bước này, hãy xem tài liệu về Xác thực qua điện thoại trên iOS của Firebase.
Web: Đảm bảo rằng bạn đã thêm miền ứng dụng của mình vào bảng điều khiển Firebase, trong phần Miền chuyển hướng OAuth.
Bật tính năng xác thực đa yếu tố
Mở trang Xác thực > Phương thức đăng nhập của bảng điều khiển Firebase.
Trong phần Nâng cao, hãy bật tính năng Xác thực đa yếu tố qua SMS.
Bạn cũng nên nhập số điện thoại mà bạn sẽ dùng để kiểm thử ứng dụng. Mặc dù không bắt buộc, nhưng bạn nên đăng ký số điện thoại thử nghiệm để tránh bị điều tiết trong quá trình phát triển.
Nếu bạn chưa uỷ quyền cho miền của ứng dụng, hãy thêm miền đó vào danh sách cho phép trên trang Xác thực > Cài đặt của bảng điều khiển Firebase.
Chọn mẫu đăng ký
Bạn có thể chọn liệu ứng dụng của mình có yêu cầu xác thực đa yếu tố hay không, cũng như cách thức và thời điểm đăng ký người dùng. Sau đây là một số mẫu phổ biến:
Đăng ký yếu tố thứ hai của người dùng trong quá trình đăng ký. Sử dụng phương thức này nếu ứng dụng của bạn yêu cầu xác thực đa yếu tố cho tất cả người dùng.
Cung cấp lựa chọn có thể bỏ qua để đăng ký yếu tố thứ hai trong quá trình đăng ký. Các ứng dụng muốn khuyến khích nhưng không bắt buộc phải sử dụng phương thức xác thực đa yếu tố có thể ưu tiên phương pháp này.
Cho phép thêm yếu tố thứ hai từ trang quản lý tài khoản hoặc hồ sơ của người dùng, thay vì màn hình đăng ký. Điều này giúp giảm thiểu sự phiền toái trong quá trình đăng ký, đồng thời vẫn cung cấp phương thức xác thực đa yếu tố cho những người dùng nhạy cảm về bảo mật.
Yêu cầu thêm yếu tố thứ hai khi người dùng muốn truy cập vào các tính năng có yêu cầu bảo mật cao hơn.
Đăng ký yếu tố thứ hai
Cách đăng ký một yếu tố phụ mới cho người dùng:
Xác thực lại người dùng.
Yêu cầu người dùng nhập số điện thoại của họ.
Nhận phiên xác thực đa yếu tố cho người dùng:
final multiFactorSession = await user.multiFactor.getSession();
Xác minh số điện thoại bằng một phiên nhiều yếu tố và lệnh gọi lại:
await FirebaseAuth.instance.verifyPhoneNumber( multiFactorSession: multiFactorSession, phoneNumber: phoneNumber, verificationCompleted: (_) {}, verificationFailed: (_) {}, codeSent: (String verificationId, int? resendToken) async { // The SMS verification code has been sent to the provided phone number. // ... }, codeAutoRetrievalTimeout: (_) {}, );
Sau khi gửi mã SMS, hãy yêu cầu người dùng xác minh mã:
final credential = PhoneAuthProvider.credential( verificationId: verificationId, smsCode: smsCode, );
Hoàn tất quy trình đăng ký:
await user.multiFactor.enroll( PhoneMultiFactorGenerator.getAssertion( credential, ), );
Mã dưới đây cho thấy ví dụ đầy đủ về cách đăng ký yếu tố thứ hai:
final session = await user.multiFactor.getSession();
final auth = FirebaseAuth.instance;
await auth.verifyPhoneNumber(
multiFactorSession: session,
phoneNumber: phoneController.text,
verificationCompleted: (_) {},
verificationFailed: (_) {},
codeSent: (String verificationId, int? resendToken) async {
// See `firebase_auth` example app for a method of retrieving user's sms code:
// https://github.com/firebase/flutterfire/blob/main/packages/firebase_auth/firebase_auth/example/lib/auth.dart#L591
final smsCode = await getSmsCodeFromUser(context);
if (smsCode != null) {
// Create a PhoneAuthCredential with the code
final credential = PhoneAuthProvider.credential(
verificationId: verificationId,
smsCode: smsCode,
);
try {
await user.multiFactor.enroll(
PhoneMultiFactorGenerator.getAssertion(
credential,
),
);
} on FirebaseAuthException catch (e) {
print(e.message);
}
}
},
codeAutoRetrievalTimeout: (_) {},
);
Xin chúc mừng! Bạn đã đăng ký thành công một yếu tố xác thực thứ hai cho người dùng.
Đăng nhập người dùng bằng yếu tố thứ hai
Cách đăng nhập cho người dùng bằng phương thức xác minh 2 yếu tố qua SMS:
Đăng nhập người dùng bằng yếu tố đầu tiên, sau đó phát hiện ngoại lệ
FirebaseAuthMultiFactorException
. Lỗi này chứa một trình phân giải mà bạn có thể sử dụng để lấy các yếu tố thứ hai đã đăng ký của người dùng. Tệp này cũng chứa một phiên cơ bản chứng minh rằng người dùng đã xác thực thành công bằng yếu tố đầu tiên.Ví dụ: nếu yếu tố đầu tiên của người dùng là email và mật khẩu:
try { await _auth.signInWithEmailAndPassword( email: emailController.text, password: passwordController.text, ); // User is not enrolled with a second factor and is successfully // signed in. // ... } on FirebaseAuthMultiFactorException catch (e) { // The user is a multi-factor user. Second factor challenge is required final resolver = e.resolver // ... }
Nếu người dùng đã đăng ký nhiều yếu tố phụ, hãy hỏi họ nên sử dụng yếu tố nào:
final session = e.resolver.session; final hint = e.resolver.hints[selectedHint];
Gửi tin nhắn xác minh đến điện thoại của người dùng kèm theo gợi ý và phiên xác thực nhiều yếu tố:
await FirebaseAuth.instance.verifyPhoneNumber( multiFactorSession: session, multiFactorInfo: hint, verificationCompleted: (_) {}, verificationFailed: (_) {}, codeSent: (String verificationId, int? resendToken) async { // ... }, codeAutoRetrievalTimeout: (_) {}, );
Gọi
resolver.resolveSignIn()
để hoàn tất quy trình xác thực phụ:final smsCode = await getSmsCodeFromUser(context); if (smsCode != null) { // Create a PhoneAuthCredential with the code final credential = PhoneAuthProvider.credential( verificationId: verificationId, smsCode: smsCode, ); try { await e.resolver.resolveSignIn( PhoneMultiFactorGenerator.getAssertion(credential) ); } on FirebaseAuthException catch (e) { print(e.message); } }
Mã dưới đây cho thấy ví dụ đầy đủ về cách đăng nhập người dùng đa yếu tố:
try {
await _auth.signInWithEmailAndPassword(
email: emailController.text,
password: passwordController.text,
);
} on FirebaseAuthMultiFactorException catch (e) {
setState(() {
error = '${e.message}';
});
final firstHint = e.resolver.hints.first;
if (firstHint is! PhoneMultiFactorInfo) {
return;
}
await FirebaseAuth.instance.verifyPhoneNumber(
multiFactorSession: e.resolver.session,
multiFactorInfo: firstHint,
verificationCompleted: (_) {},
verificationFailed: (_) {},
codeSent: (String verificationId, int? resendToken) async {
// See `firebase_auth` example app for a method of retrieving user's sms code:
// https://github.com/firebase/flutterfire/blob/main/packages/firebase_auth/firebase_auth/example/lib/auth.dart#L591
final smsCode = await getSmsCodeFromUser(context);
if (smsCode != null) {
// Create a PhoneAuthCredential with the code
final credential = PhoneAuthProvider.credential(
verificationId: verificationId,
smsCode: smsCode,
);
try {
await e.resolver.resolveSignIn(
PhoneMultiFactorGenerator.getAssertion(
credential,
),
);
} on FirebaseAuthException catch (e) {
print(e.message);
}
}
},
codeAutoRetrievalTimeout: (_) {},
);
} catch (e) {
...
}
Xin chúc mừng! Bạn đã đăng nhập thành công cho một người dùng bằng phương thức xác thực nhiều yếu tố.
Bước tiếp theo
- Quản lý người dùng xác thực nhiều yếu tố bằng cách lập trình với SDK dành cho quản trị viên.