Menambahkan autentikasi multi-faktor ke aplikasi iOS
Dokumen ini menunjukkan cara menambahkan autentikasi multi-faktor SMS ke aplikasi iOS Anda.
Autentikasi multi-faktor meningkatkan keamanan aplikasi Anda. Meskipun penyerang sering membobol sandi dan akun media sosial, menyadap pesan teks lebih sulit dilakukan.
Sebelum memulai
Aktifkan minimal satu penyedia yang mendukung autentikasi multi-faktor. Setiap penyedia mendukung MFA, kecuali autentikasi dengan ponsel, autentikasi anonim, dan Apple Game Center.
Pastikan aplikasi Anda memverifikasi email pengguna. MFA memerlukan verifikasi email. Tindakan ini mencegah pelaku kejahatan mendaftar ke layanan dengan email yang bukan miliknya, lalu mengunci pemilik sebenarnya dari akunnya dengan menambahkan faktor kedua.
Mengaktifkan autentikasi multi-faktor
Buka halaman Identity Platform MFA di Konsol Google Cloud.
Buka halaman MFAPada kotak berjudul SMS-Based Multi-Factor Authentication, klik Enable.
Masukkan nomor telepon yang akan digunakan untuk menguji aplikasi. Meskipun opsional, mendaftarkan nomor telepon pengujian sangat direkomendasikan untuk menghindari throttling selama pengembangan.
Jika Anda belum memberikan otorisasi pada domain aplikasi, tambahkan domain tersebut ke daftar yang diizinkan dengan mengklik Tambahkan domain di sebelah kanan.
Klik Simpan.
Memverifikasi aplikasi
Identity Platform perlu memverifikasi bahwa permintaan SMS berasal dari aplikasi Anda. Anda dapat melakukannya dengan dua cara:
Notifikasi APNs senyap: Saat Anda memproses login pengguna untuk pertama kalinya, Identity Platform dapat mengirim notifikasi push senyap ke perangkat pengguna. Autentikasi dapat dilanjutkan jika aplikasi menerima notifikasi. Perlu diperhatikan bahwa mulai iOS 8.0, Anda tidak perlu meminta pengguna mengizinkan notifikasi push untuk menggunakan metode ini.
Verifikasi reCAPTCHA: Jika Anda tidak dapat mengirim notifikasi senyap (misalnya, karena pengguna telah menonaktifkan refresh di latar belakang, atau Anda menguji aplikasi di simulator iOS), Anda dapat menggunakan reCAPTCHA. Dalam banyak kasus, reCAPTCHA akan otomatis selesai dengan sendirinya tanpa interaksi pengguna.
Menggunakan notifikasi senyap
Untuk mengaktifkan notifikasi APNs agar dapat digunakan dengan Identity Platform:
Di Xcode, aktifkan notifikasi push untuk project Anda.
Upload kunci autentikasi APNs Anda menggunakan Firebase Console (perubahan Anda akan otomatis diterapkan ke Google Cloud Identity Platform). Jika belum memiliki kunci autentikasi APNs, lihat bagian Mengonfigurasi APNs dengan FCM untuk mempelajari cara mendapatkannya.
Buka Firebase Console.
Buka Project Settings.
Pilih tab Cloud Messaging.
Di bagian APNs authentication key, pada bagian iOS app configuration, klik Upload.
Pilih kunci Anda.
Tambahkan ID kunci untuk kunci tersebut. Anda dapat menemukan ID kunci di bagian Certificates, Identifiers & Profiles di Apple Developer Member Center.
Klik Upload.
Jika sudah memiliki sertifikat APNs, Anda dapat menguploadnya.
Menggunakan verifikasi reCAPTCHA
Untuk mengaktifkan SDK klien agar dapat menggunakan reCAPTCHA:
Buka konfigurasi project di Xcode.
Klik dua kali pada nama project dalam tampilan hierarki di sebelah kiri.
Pilih aplikasi dari bagian Targets.
Pilih tab Info.
Perluas bagian URL Types.
Klik tombol +.
Masukkan client ID terbalik di kolom URL Schemes. Anda dapat menemukan nilai ini tercantum di file konfigurasi
GoogleService-Info.plist
sebagaiREVERSED_CLIENT_ID
.
Jika sudah selesai, konfigurasi Anda akan terlihat seperti contoh berikut:
Secara opsional, Anda dapat menyesuaikan cara aplikasi menyajikan SFSafariViewController
atau UIWebView
saat menampilkan reCAPTCHA. Untuk melakukannya, buat class kustom yang sesuai dengan protokol FIRAuthUIDelegate
, dan teruskan ke verifyPhoneNumber:UIDelegate:completion:
.
Memilih pola pendaftaran
Anda dapat memilih apakah aplikasi memerlukan autentikasi multi-faktor atau tidak, serta cara dan waktu untuk mendaftarkan pengguna. Beberapa pola yang umum antara lain:
Mendaftarkan faktor kedua pengguna sebagai bagian dari pendaftaran. Gunakan metode ini jika aplikasi Anda memerlukan autentikasi multi-faktor untuk semua pengguna. Perhatikan bahwa akun harus memiliki alamat email terverifikasi untuk mendaftarkan faktor kedua, sehingga alur pendaftaran harus mengakomodasi hal ini.
Menawarkan opsi yang dapat dilewati untuk mendaftarkan faktor kedua selama pendaftaran. Aplikasi yang ingin mendukung, tetapi tidak memerlukan, autentikasi multi-faktor dapat memilih pendekatan ini.
Memungkinkan untuk menambahkan faktor kedua dari halaman pengelolaan akun atau profil pengguna, bukan dari layar pendaftaran. Hal ini akan meminimalkan hambatan selama proses pendaftaran, sekaligus tetap menyediakan autentikasi multi-faktor untuk pengguna yang rentan terhadap ancaman keamanan.
Memerlukan penambahan faktor kedua secara inkremental saat pengguna ingin mengakses fitur dengan persyaratan keamanan yang ditingkatkan.
Mendaftarkan faktor kedua
Untuk mendaftarkan faktor sekunder baru untuk pengguna:
Autentikasi ulang pengguna.
Minta pengguna untuk memasukkan nomor teleponnya.
Dapatkan sesi multi-faktor untuk pengguna:
Swift
authResult.user.multiFactor.getSessionWithCompletion() { (session, error) in // ... }
Objective-C
[authResult.user.multiFactor getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session, NSError * _Nullable error) { // ... }];
Kirim pesan verifikasi ke ponsel pengguna. Pastikan nomor telepon diformat dengan
+
utama dan tanpa tanda baca atau spasi kosong lainnya (misalnya:+15105551234
)Swift
// Send SMS verification code. PhoneAuthProvider.provider().verifyPhoneNumber( phoneNumber, uiDelegate: nil, multiFactorSession: session) { (verificationId, error) in // verificationId will be needed for enrollment completion. }
Objective-C
// Send SMS verification code. [FIRPhoneAuthProvider.provider verifyPhoneNumber:phoneNumber UIDelegate:nil multiFactorSession:session completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { // verificationId will be needed for enrollment completion. }];
Meskipun tidak diwajibkan, sebaiknya beri tahu pengguna terlebih dahulu bahwa mereka akan menerima pesan SMS, dan dikenakan tarif standar.
Metode
verifyPhoneNumber()
memulai proses verifikasi aplikasi di latar belakang menggunakan notifikasi push senyap. Jika notifikasi push senyap tidak tersedia, tantangan reCAPTCHA akan dikeluarkan.Setelah kode SMS dikirim, minta pengguna untuk memverifikasi kode tersebut. Kemudian, gunakan respons untuk membuat
PhoneAuthCredential
:Swift
// Ask user for the verification code. Then: let credential = PhoneAuthProvider.provider().credential( withVerificationID: verificationId, verificationCode: verificationCode)
Objective-C
// Ask user for the SMS verification code. Then: FIRPhoneAuthCredential *credential = [FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID verificationCode:kPhoneSecondFactorVerificationCode];
Lakukan inisialisasi objek pernyataan:
Swift
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
Objective-C
FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
Selesaikan pendaftaran. Secara opsional, Anda dapat menentukan nama tampilan untuk faktor kedua. Hal ini berguna bagi pengguna dengan beberapa faktor kedua, karena nomor telepon disamarkan selama alur autentikasi (misalnya, +1******1234).
Swift
// Complete enrollment. This will update the underlying tokens // and trigger ID token change listener. user.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in // ... }
Objective-C
// Complete enrollment. This will update the underlying tokens // and trigger ID token change listener. [authResult.user.multiFactor enrollWithAssertion:assertion displayName:nil completion:^(NSError * _Nullable error) { // ... }];
Kode di bawah menunjukkan contoh lengkap proses pendaftaran faktor kedua:
Swift
let user = Auth.auth().currentUser
user?.multiFactor.getSessionWithCompletion({ (session, error) in
// Send SMS verification code.
PhoneAuthProvider.provider().verifyPhoneNumber(
phoneNumber,
uiDelegate: nil,
multiFactorSession: session
) { (verificationId, error) in
// verificationId will be needed for enrollment completion.
// Ask user for the verification code.
let credential = PhoneAuthProvider.provider().credential(
withVerificationID: verificationId!,
verificationCode: phoneSecondFactorVerificationCode)
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
// Complete enrollment. This will update the underlying tokens
// and trigger ID token change listener.
user?.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in
// ...
}
}
})
Objective-C
FIRUser *user = FIRAuth.auth.currentUser;
[user.multiFactor getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session,
NSError * _Nullable error) {
// Send SMS verification code.
[FIRPhoneAuthProvider.provider
verifyPhoneNumber:phoneNumber
UIDelegate:nil
multiFactorSession:session
completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
// verificationId will be needed for enrollment completion.
// Ask user for the verification code.
// ...
// Then:
FIRPhoneAuthCredential *credential =
[FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID
verificationCode:kPhoneSecondFactorVerificationCode];
FIRMultiFactorAssertion *assertion =
[FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
// Complete enrollment. This will update the underlying tokens
// and trigger ID token change listener.
[user.multiFactor enrollWithAssertion:assertion
displayName:displayName
completion:^(NSError * _Nullable error) {
// ...
}];
}];
}];
Selamat! Anda berhasil mendaftarkan faktor autentikasi kedua untuk pengguna.
Memproses login pengguna dengan faktor kedua
Untuk memproses login pengguna dengan verifikasi SMS dua faktor:
Proses login pengguna dengan faktor pertamanya, lalu tangkap error yang menunjukkan bahwa autentikasi multi faktor diperlukan. Error ini berisi resolver, petunjuk tentang faktor kedua yang didaftarkan, dan sesi yang mendasarinya yang membuktikan bahwa pengguna berhasil diautentikasi dengan faktor pertama.
Misalnya, jika faktor pertama pengguna adalah email dan sandi:
Swift
Auth.auth().signIn( withEmail: email, password: password ) { (result, error) in let authError = error as NSError if authError?.code == AuthErrorCode.secondFactorRequired.rawValue { // The user is a multi-factor user. Second factor challenge is required. let resolver = authError!.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver // ... } else { // Handle other errors such as wrong password. } }
Objective-C
[FIRAuth.auth signInWithEmail:email password:password completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error == nil || error.code != FIRAuthErrorCodeSecondFactorRequired) { // User is not enrolled with a second factor and is successfully signed in. // ... } else { // The user is a multi-factor user. Second factor challenge is required. } }];
Jika faktor pertama pengguna adalah penyedia gabungan, seperti OAuth, tangkap error setelah memanggil
getCredentialWith()
.Jika pengguna telah mendaftarkan beberapa faktor sekunder, tanyakan kepada mereka faktor mana yang ingin digunakan. Anda bisa mendapatkan nomor telepon yang disamarkan dengan
resolver.hints[selectedIndex].phoneNumber
dan nama tampilan denganresolver.hints[selectedIndex].displayName
.Swift
// Ask user which second factor to use. Then: if resolver.hints[selectedIndex].factorID == PhoneMultiFactorID { // User selected a phone second factor. // ... } else if resolver.hints[selectedIndex].factorID == TotpMultiFactorID { // User selected a TOTP second factor. // ... } else { // Unsupported second factor. }
Objective-C
FIRMultiFactorResolver *resolver = (FIRMultiFactorResolver *) error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey]; // Ask user which second factor to use. Then: FIRPhoneMultiFactorInfo *hint = (FIRPhoneMultiFactorInfo *) resolver.hints[selectedIndex]; if (hint.factorID == FIRPhoneMultiFactorID) { // User selected a phone second factor. // ... } else if (hint.factorID == FIRTOTPMultiFactorID) { // User selected a TOTP second factor. // ... } else { // Unsupported second factor. }
Kirim pesan verifikasi ke ponsel pengguna:
Swift
// Send SMS verification code. let hint = resolver.hints[selectedIndex] as! PhoneMultiFactorInfo PhoneAuthProvider.provider().verifyPhoneNumber( with: hint, uiDelegate: nil, multiFactorSession: resolver.session ) { (verificationId, error) in // verificationId will be needed for sign-in completion. }
Objective-C
// Send SMS verification code [FIRPhoneAuthProvider.provider verifyPhoneNumberWithMultiFactorInfo:hint UIDelegate:nil multiFactorSession:resolver.session completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { if (error != nil) { // Failed to verify phone number. } }];
Setelah kode SMS dikirim, minta pengguna untuk memverifikasi kode dan menggunakannya untuk membuat
PhoneAuthCredential
:Swift
// Ask user for the verification code. Then: let credential = PhoneAuthProvider.provider().credential( withVerificationID: verificationId!, verificationCode: verificationCodeFromUser)
Objective-C
// Ask user for the SMS verification code. Then: FIRPhoneAuthCredential *credential = [FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID verificationCode:verificationCodeFromUser];
Lakukan inisialisasi objek pernyataan dengan kredensial:
Swift
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
Objective-C
FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
Selesaikan proses login. Selanjutnya, Anda dapat mengakses hasil login asli, yang mencakup kredensial autentikasi dan data khusus penyedia standar:
Swift
// Complete sign-in. This will also trigger the Auth state listeners. resolver.resolveSignIn(with: assertion) { (authResult, error) in // authResult will also contain the user, additionalUserInfo, optional // credential (null for email/password) associated with the first factor sign-in. // For example, if the user signed in with Google as a first factor, // authResult.additionalUserInfo will contain data related to Google provider that // the user signed in with. // user.credential contains the Google OAuth credential. // user.credential.accessToken contains the Google OAuth access token. // user.credential.idToken contains the Google OAuth ID token. }
Objective-C
// Complete sign-in. [resolver resolveSignInWithAssertion:assertion completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error != nil) { // User successfully signed in with the second factor phone number. } }];
Kode di bawah menunjukkan contoh lengkap proses login pengguna multi-faktor:
Swift
Auth.auth().signIn(
withEmail: email,
password: password
) { (result, error) in
let authError = error as NSError?
if authError?.code == AuthErrorCode.secondFactorRequired.rawValue {
let resolver =
authError!.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver
// Ask user which second factor to use.
// ...
// Then:
let hint = resolver.hints[selectedIndex] as! PhoneMultiFactorInfo
// Send SMS verification code
PhoneAuthProvider.provider().verifyPhoneNumber(
with: hint,
uiDelegate: nil,
multiFactorSession: resolver.session
) { (verificationId, error) in
if error != nil {
// Failed to verify phone number.
}
// Ask user for the SMS verification code.
// ...
// Then:
let credential = PhoneAuthProvider.provider().credential(
withVerificationID: verificationId!,
verificationCode: verificationCodeFromUser)
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
// Complete sign-in.
resolver.resolveSignIn(with: assertion) { (authResult, error) in
if error != nil {
// User successfully signed in with the second factor phone number.
}
}
}
}
}
Objective-C
[FIRAuth.auth signInWithEmail:email
password:password
completion:^(FIRAuthDataResult * _Nullable authResult,
NSError * _Nullable error) {
if (error == nil || error.code != FIRAuthErrorCodeSecondFactorRequired) {
// User is not enrolled with a second factor and is successfully signed in.
// ...
} else {
FIRMultiFactorResolver *resolver =
(FIRMultiFactorResolver *) error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
// Ask user which second factor to use.
// ...
// Then:
FIRPhoneMultiFactorInfo *hint = (FIRPhoneMultiFactorInfo *) resolver.hints[selectedIndex];
// Send SMS verification code
[FIRPhoneAuthProvider.provider
verifyPhoneNumberWithMultiFactorInfo:hint
UIDelegate:nil
multiFactorSession:resolver.session
completion:^(NSString * _Nullable verificationID,
NSError * _Nullable error) {
if (error != nil) {
// Failed to verify phone number.
}
// Ask user for the SMS verification code.
// ...
// Then:
FIRPhoneAuthCredential *credential =
[FIRPhoneAuthProvider.provider
credentialWithVerificationID:verificationID
verificationCode:kPhoneSecondFactorVerificationCode];
FIRMultiFactorAssertion *assertion =
[FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
// Complete sign-in.
[resolver resolveSignInWithAssertion:assertion
completion:^(FIRAuthDataResult * _Nullable authResult,
NSError * _Nullable error) {
if (error != nil) {
// User successfully signed in with the second factor phone number.
}
}];
}];
}
}];
Selamat! Anda berhasil memproses login pengguna menggunakan autentikasi multi-faktor.
Langkah selanjutnya
- Mengelola pengguna multi-faktor secara terprogram dengan Admin SDK.