Aggiungere l'autenticazione a più fattori TOTP all'app per iOS

Se hai eseguito l'upgrade a Firebase Authentication with Identity Platform, puoi aggiungere l'autenticazione a più fattori (MFA) con password temporanea e monouso (TOTP) alla tua app.

Firebase Authentication with Identity Platform ti consente di utilizzare una password temporanea e monouso (TOTP) come fattore aggiuntivo per l'autenticazione a più fattori. Quando attivi questa funzionalità, gli utenti che tentano di accedere alla tua app vedono una richiesta di TOTP. Per generarlo, deve utilizzare un'app di autenticazione in grado di generare codici TOTP validi, come Google Authenticator.

Prima di iniziare

  1. Attiva almeno un provider che supporti l'autenticazione a più fattori. Tieni presente che tutti i fornitori tranne i seguenti supportano l'autenticazione a più fattori:

    • Autenticazione telefonica
    • Autenticazione anonima
    • Token di autorizzazione personalizzati
    • Apple Game Center
  2. Assicurati che la tua app verifichi gli indirizzi email degli utenti. La MFA richiede la verifica dell'email. In questo modo, i malintenzionati non possono registrarsi a un servizio con un indirizzo email che non è di loro proprietà e bloccare l'accesso al proprietario effettivo dell'indirizzo email aggiungendo un secondo fattore.

  3. Se non l'hai ancora fatto, installa l'SDK Firebase Apple.

    L'autenticazione a più fattori TOTP è supportata solo dall'SDK Apple versione 10.12.0 e successive e solo su iOS.

Abilitare l'autenticazione a più fattori TOTP

Per abilitare TOTP come secondo fattore, utilizza Admin SDK o chiama l'endpoint REST di configurazione del progetto.

Per utilizzare Admin SDK:

  1. Se non lo hai ancora fatto, installa l'SDK Firebase Admin Node.js.

    L'autenticazione a più fattori TOTP è supportata solo nelle versioni 11.6.0 e successive dell'SDK Firebase Admin Node.js.

  2. Esegui questo comando:

    import { getAuth } from 'firebase-admin/auth';
    
    getAuth().projectConfigManager().updateProjectConfig(
    {
          multiFactorConfig: {
              providerConfigs: [{
                  state: "ENABLED",
                  totpProviderConfig: {
                      adjacentIntervals: NUM_ADJ_INTERVALS
                  }
              }]
          }
    })
    

    Sostituisci quanto segue:

    • NUM_ADJ_INTERVALS: il numero di intervalli di finestre temporali adiacenti da cui accettare i TOTP, da zero a dieci. Il valore predefinito è cinque.

      I TOTP funzionano garantendo che quando due parti (il richiedente e il validatore) generano OTP nella stessa finestra temporale (in genere di 30 secondi di durata), generano la stessa password. Tuttavia, per tenere conto della deriva dell'orologio tra le parti e del tempo di risposta umano, puoi configurare il servizio TOTP in modo che accetti anche i TOTP delle finestre adiacenti.

Per abilitare l'autenticazione a più fattori TOTP utilizzando l'API REST, esegui il comando seguente:

curl -X PATCH "https://identitytoolkit.googleapis.com/admin/v2/projects/PROJECT_ID/config?updateMask=mfa" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json" \
    -H "X-Goog-User-Project: PROJECT_ID" \
    -d \
    '{
        "mfa": {
          "providerConfigs": [{
            "state": "ENABLED",
            "totpProviderConfig": {
              "adjacentIntervals": NUM_ADJ_INTERVALS
            }
          }]
       }
    }'

Sostituisci quanto segue:

  • PROJECT_ID: l'ID progetto.
  • NUM_ADJ_INTERVALS: Il numero di intervalli della finestra temporale, da zero a dieci. Il valore predefinito è cinque.

    I TOTP funzionano garantendo che quando due parti (il richiedente e il validatore) generano OTP nella stessa finestra temporale (in genere di 30 secondi di durata), generano la stessa password. Tuttavia, per tenere conto della deriva dell'orologio tra le parti e del tempo di risposta umano, puoi configurare il servizio TOTP in modo che accetti anche i TOTP delle finestre adiacenti.

Scegliere un pattern di registrazione

Puoi scegliere se la tua app richiede l'autenticazione a più fattori e come e quando registrare gli utenti. Alcuni pattern comuni includono:

  • Registra il secondo fattore dell'utente durante la registrazione. Utilizza questo metodo se la tua app richiede l'autenticazione a più fattori per tutti gli utenti.

  • Offri un'opzione ignorabile per registrare un secondo fattore durante la registrazione. Se vuoi incoraggiare, ma non richiedere, l'autenticazione a più fattori nella tua app, puoi utilizzare questo approccio.

  • Offrire la possibilità di aggiungere un secondo fattore dalla pagina di gestione dell'account o del profilo dell'utente, anziché dalla schermata di registrazione. In questo modo, l'attrito durante la procedura di registrazione viene ridotto al minimo, pur rendendo l'autenticazione a più fattori disponibile per gli utenti sensibili alla sicurezza.

  • Richiedi l'aggiunta di un secondo fattore in modo incrementale quando l'utente vuole accedere a funzionalità con requisiti di sicurezza più elevati.

Registra utenti in MFA TOTP

Dopo aver abilitato l'autenticazione a più fattori basata su TOTP come secondo fattore per la tua app, implementa la logica lato client per registrare gli utenti all'autenticazione a più fattori basata su TOTP:

  1. Esegui nuovamente l'autenticazione dell'utente.

  2. Genera un secret TOTP per l'utente autenticato:

    // Generate a TOTP secret.
    guard let mfaSession = try? await currentUser.multiFactor.session() else { return }
    guard let totpSecret = try? await TOTPMultiFactorGenerator.generateSecret(with: mfaSession) else { return }
    
    // Display the secret to the user and prompt them to enter it into their
    // authenticator app. (See the next step.)
    
  3. Mostra il secret all'utente e chiedigli di inserirlo nell'app Authenticator:

    // Display this key:
    let secret = totpSecret.sharedSecretKey()
    

    Oltre a visualizzare la chiave segreta, puoi tentare di aggiungerla automaticamente all'app di autenticazione predefinita del dispositivo. Per farlo, genera un URI della chiave compatibile con Google Authenticator e passalo a openInOTPApp(withQRCodeURL:):

    let otpAuthUri = totpSecret.generateQRCodeURL(
        withAccountName: currentUser.email ?? "default account",
        issuer: "Your App Name")
    totpSecret.openInOTPApp(withQRCodeURL: otpAuthUri)
    

    Dopo che l'utente aggiunge il segreto all'app di autenticazione, questa inizia a generare TOTP.

  4. Chiedi all'utente di digitare il TOTP visualizzato dall'app di autenticazione e utilizzarlo per completare la registrazione MFA:

    // Ask the user for a verification code from the authenticator app.
    let verificationCode = // Code from user input.
    
    // Finalize the enrollment.
    let multiFactorAssertion = TOTPMultiFactorGenerator.assertionForEnrollment(
        with: totpSecret,
        oneTimePassword: verificationCode)
    do {
        try await currentUser.multiFactor.enroll(
            with: multiFactorAssertion,
            displayName: "TOTP")
    } catch {
        // Wrong or expired OTP. Re-prompt the user.
    }
    

Accedere con un secondo fattore

Per consentire l'accesso degli utenti con l'autenticazione a più fattori TOTP, utilizza il seguente codice:

  1. Chiama uno dei metodi signIn(with...:) come faresti se non utilizzassi l'autenticazione a più fattori (ad esempio, signIn(withEmail:password:)). Se il metodo genera un errore con il codice secondFactorRequired, avvia il flusso MFA della tua app.

    do {
        let authResult = try await Auth.auth().signIn(withEmail: email, password: password)
    
        // If the user is not enrolled with a second factor and provided valid
        // credentials, sign-in succeeds.
    
        // (If your app requires MFA, this could be considered an error
        // condition, which you would resolve by forcing the user to enroll a
        // second factor.)
    
        // ...
    } catch let error as AuthErrorCode where error.code == .secondFactorRequired {
        // Initiate your second factor sign-in flow. (See next step.)
        // ...
    } catch {
        // Other auth error.
        throw error
    }
    
  2. Il flusso MFA della tua app deve innanzitutto chiedere all'utente di scegliere il secondo fattore che vuole utilizzare. Puoi ottenere un elenco dei secondi fattori supportati esaminando la proprietà hints di un'istanza MultiFactorResolver:

    let mfaKey = AuthErrorUserInfoMultiFactorResolverKey
    guard let resolver = error.userInfo[mfaKey] as? MultiFactorResolver else { return }
    let enrolledFactors = resolver.hints.map(\.displayName)
    
  3. Se l'utente sceglie di utilizzare TOTP, chiedigli di digitare il TOTP visualizzato nell'app di autenticazione e di utilizzarlo per accedere:

    let multiFactorInfo = resolver.hints[selectedIndex]
    switch multiFactorInfo.factorID {
    case TOTPMultiFactorID:
        let otpFromAuthenticator = // OTP typed by the user.
        let assertion = TOTPMultiFactorGenerator.assertionForSignIn(
            withEnrollmentID: multiFactorInfo.uid,
            oneTimePassword: otpFromAuthenticator)
        do {
            let authResult = try await resolver.resolveSignIn(with: assertion)
        } catch {
            // Wrong or expired OTP. Re-prompt the user.
        }
    default:
        return
    }
    

Annullare la registrazione all'autenticazione a più fattori basata su TOTP

Questa sezione descrive come gestire l'annullamento della registrazione di un utente all'autenticazione a più fattori TOTP.

Se un utente ha eseguito la registrazione a più opzioni MFA e se annulla la registrazione dell'opzione attivata più di recente, riceve un auth/user-token-expired e viene disconnesso. L'utente deve accedere di nuovo e verificare le proprie credenziali esistenti, ad esempio un indirizzo email e una password.

Per annullare la registrazione dell'utente, gestire l'errore e attivare la riautenticazione, utilizza il seguente codice:

guard let currentUser = Auth.auth().currentUser else { return }

// Prompt the user to select a factor to unenroll, from this array:
currentUser.multiFactor.enrolledFactors

// ...

// Unenroll the second factor.
let multiFactorInfo = currentUser.multiFactor.enrolledFactors[selectedIndex]
do {
    try await currentUser.multiFactor.unenroll(with: multiFactorInfo)
} catch let error as AuthErrorCode where error.code == .invalidUserToken {
    // Second factor unenrolled, but the user was signed out. Re-authenticate
    // them.
}

Passaggi successivi