Jeśli korzystasz z usługi Uwierzytelnianie Firebase z Identity Platform, możesz dodać do aplikacji Flutter uwierzytelnianie wielopoziomowe z użyciem SMS-ów.
Uwierzytelnianie wielopoziomowe (MFA) zwiększa poziom bezpieczeństwa aplikacji. Osoby przeprowadzające ataki często przejmują hasła i konta społecznościowe, ale przechwycenie SMS-a jest dużo trudniejsze.
Zanim zaczniesz
Włącz co najmniej jednego dostawcę, który obsługuje uwierzytelnianie wielopoziomowe. Każdy dostawca obsługuje uwierzytelnianie wieloskładnikowe z wyjątkiem uwierzytelniania przez telefon, uwierzytelniania anonimowego i Apple Game Center.
Upewnij się, że aplikacja weryfikuje adresy e-mail użytkowników. MFA wymaga potwierdzenia adresu e-mail. Dzięki temu osoby o złośliwych zamiarach nie mogą zarejestrować się w usłudze, podając adres e-mail, którego nie są właścicielami, a potem zablokować dostęp prawdziwemu właścicielowi, dodając drugi czynnik.
Android: jeśli nie ustawiono jeszcze identyfikatora SHA-256 aplikacji w konsoli Firebase, zrób to. Więcej informacji o znajdowaniu identyfikatora SHA-256 aplikacji znajdziesz w artykule Uwierzytelnianie klienta.
iOS: w Xcode włącz powiadomienia push dla projektu i upewnij się, że klucz uwierzytelniania APNs jest skonfigurowany w Komunikacji w chmurze Firebase (FCM). Dodatkowo musisz włączyć tryby działania w tle, aby wysyłać powiadomienia z dalsza. Szczegółowe informacje o tym kroku znajdziesz w dokumentacji Uwierzytelniania przez telefon w Firebase na iOS.
Internet: sprawdź, czy dodałeś domenę aplikacji w konsoli Firebase w sekcji Domeny przekierowania OAuth.
Włączanie uwierzytelniania wielopoziomowego
W konsoli Firebase otwórz stronę Uwierzytelnianie > Metoda logowania.
W sekcji Zaawansowane włącz Uwierzytelnianie wielopoziomowe z użyciem SMS-ów.
Musisz też podać numery telefonów, których użyjesz do testowania aplikacji. Chociaż rejestracja numerów telefonów do testów jest opcjonalna, zdecydowanie ją zalecamy, ponieważ pozwoli uniknąć ograniczeń podczas programowania.
Jeśli nie autoryzujesz jeszcze domeny aplikacji, dodaj ją do listy dozwolonych na stronie Uwierzytelnianie > Ustawienia konsoli Firebase.
Wybieranie schematu rejestracji
Możesz wybrać, czy Twoja aplikacja wymaga uwierzytelniania wielopoziomowego oraz jak i kiedy rejestrować użytkowników. Typowe wzorce to m.in.:
Zarejestruj drugi składnik uwierzytelniający użytkownika w ramach rejestracji. Użyj tej metody, jeśli aplikacja wymaga uwierzytelniania wielopoziomowego od wszystkich użytkowników.
Zaoferuj opcję pominięcia rejestracji drugiego czynnika podczas rejestracji. Aplikacje, które zachęcają do korzystania z uwierzytelniania wielopoziomowego, ale nie wymagają tego, mogą preferować to podejście.
Dodanie możliwości dodawania drugiego czynnika na koncie użytkownika lub na stronie zarządzania profilem zamiast na ekranie rejestracji. Pozwala to zminimalizować problemy podczas procesu rejestracji, a jednocześnie udostępnia uwierzytelnianie wielopoziomowe użytkownikom, którzy przykładają dużą wagę do bezpieczeństwa.
Wymagaj stopniowego dodawania drugiego czynnika, gdy użytkownik chce uzyskać dostęp do funkcji o większych wymaganiach bezpieczeństwa.
Rejestrowanie drugiego składnika
Aby zarejestrować nowy czynnik dodatkowy dla użytkownika:
Ponownie uwierzytelnij użytkownika.
Poproś użytkownika o wpisanie numeru telefonu.
Uzyskaj sesję uwierzytelniania wielopoziomowego dla użytkownika:
final multiFactorSession = await user.multiFactor.getSession();
Zweryfikuj numer telefonu za pomocą sesji wieloczynnikowej i wywołań zwrotnych:
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: (_) {}, );
Po wysłaniu kodu SMS poproś użytkownika o jego potwierdzenie:
final credential = PhoneAuthProvider.credential( verificationId: verificationId, smsCode: smsCode, );
Dokończ rejestrację:
await user.multiFactor.enroll( PhoneMultiFactorGenerator.getAssertion( credential, ), );
Poniżej znajdziesz kompletny przykład rejestracji drugiego czynnika:
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: (_) {},
);
Gratulacje! Użytkownik został zarejestrowany jako drugi czynnik uwierzytelniania.
Logowanie użytkowników za pomocą drugiego składnika
Aby zalogować użytkownika przy użyciu weryfikacji dwuskładnikowej SMS-em:
Zaloguj użytkownika za pomocą pierwszego czynnika, a potem przechwyć wyjątek
FirebaseAuthMultiFactorException
. Ten błąd zawiera resolver, którego możesz użyć do uzyskania zarejestrowanych drugich czynników użytkownika. Zawiera on też sesję, która potwierdza, że użytkownik został uwierzytelniony za pomocą pierwszego czynnika.Jeśli na przykład pierwszym czynnikiem użytkownika było hasło i adres e-mail:
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 // ... }
Jeśli użytkownik ma zarejestrowane dodatkowe czynniki, zapytaj, którego z nich użyć:
final session = e.resolver.session; final hint = e.resolver.hints[selectedHint];
Wyślij wiadomość weryfikacyjną na telefon użytkownika z podpowiedzią i sesją uwierzytelniania wielopoziomowego:
await FirebaseAuth.instance.verifyPhoneNumber( multiFactorSession: session, multiFactorInfo: hint, verificationCompleted: (_) {}, verificationFailed: (_) {}, codeSent: (String verificationId, int? resendToken) async { // ... }, codeAutoRetrievalTimeout: (_) {}, );
Aby ukończyć uwierzytelnianie dodatkowe, zadzwoń pod numer
resolver.resolveSignIn()
: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); } }
Poniżej znajduje się kod, który zawiera kompletny przykład logowania użytkownika w wielu krokach:
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) {
...
}
Gratulacje! Udało Ci się zalogować użytkownika za pomocą uwierzytelniania wielopoziomowego.
Co dalej?
- Zarządzaj użytkownikami korzystającymi z uwierzytelniania wielopoziomowego za pomocą pakietu Admin SDK.