Nozioni di base su AWS

Creazione di un'applicazione iOS

Crea una semplice applicazione iOS utilizzando AWS Amplify

Modulo 3: Aggiunta di un'autenticazione

In questo modulo verrà utilizzata l'interfaccia a riga di comando (CLI) di Amplify per configurare e aggiungere un'autenticazione alla tua app.

Introduzione

La prossima funzionalità che verrà aggiunta sarà l'autenticazione dell'utente. In questo modulo imparerai come autenticare un utente con l'interfaccia a riga di comando (CLI) e le librerie di Amplify sfruttando Amazon Cognito, un provider di identità utente gestito.

Imparerai anche come usare l'interfaccia utente in hosting di Cognito per presentare un intero flusso di autenticazione dell'utente, consentendo agli utenti di registrarsi, accedere e ripristinare la password con poche righe di codice.

L'utilizzo di una "interfaccia utente in hosting" significa che l'applicazione sfrutta le pagine Web Cognito per i flussi dell'interfaccia utente di accesso e registrazione. L'utente dell'applicazione viene reindirizzato a una pagina Web ospitata da Cognito e reindirizzato nuovamente all'applicazione dopo l'accesso. Ovviamente, Cognito e Amplify supportano anche l'interfaccia utente nativa, segui le istruzioni di questo workshop per ulteriori informazioni sull'interfaccia utente di autenticazione personalizzata.

Avrai modo di approfondire i seguenti aspetti

  • Creazione e distribuzione di un servizio di autenticazione
  • Configurazione dell'applicazione iOS per includere l'autenticazione dell'interfaccia utente in hosting Cognito

Concetti chiave

Librerie Amplify: le librerie di Amplify consentono di interagire con i servizi AWS da un'applicazione Web o mobile.

Autenticazione: nei software l'autenticazione è il processo di verifica e gestione dell'identità di un utente usando un servizio di autenticazione o API.

 Tempo richiesto per il completamento

10 minuti

 Servizi utilizzati

Implementazione

  • Per creare il servizio di autenticazione, apri un terminale ed esegui questo comando:

    amplify add auth
    
    ? Do you want to use the default authentication and security configuration? Select Default configuration with Social Provider and press enter
    ? How do you want users to be able to sign in? Select the default Username and press enter
    ? Do you want to configure advanced settings? Select the default No, I am done and press enter
    ? What domain name prefix do you want to use? Select the default and press enter
    Enter your redirect signin URI: type gettingstarted:// and press enter
    ? Do you want to add another redirect signin URI? Select the default N and press enter
    Enter your redirect signout URI: type gettingstarted:// and press enter
    ? Do you want to add another redirect signout URI? Select the default N and press enter
    ? Select the social providers you want to configure for your user pool: do not select any provider and press enter

    Saprai che la configurazione è andata a buon fine quando vedrai questo messaggio (il nome esatto della risorsa sarà diverso):

    Successfully added resource iosgettingstartedfc5a4717 locally
  • Ora che il servizio di autenticazione è stato configurato localmente, può essere distribuito nel cloud. In un terminale, esegui questo comando nella directory del progetto:

    amplify push
    
    # press Y when asked to continue

    Dopo qualche istante, dovrebbe essere visualizzato il seguente messaggio:

    ✔ All resources are updated in the cloud
    
    Hosted UI Endpoint: https://iosgettingstarted-dev.auth.eu-central-1.amazoncognito.com/
    Test Your Hosted UI Endpoint: https://iosgettingstarted-dev.auth.eu-central-1.amazoncognito.com/login?response_type=code&client_id=1234567890&redirect_uri=gettingstarted://
  • Prima di passare al codice, aggiungi la libreria delle autenticazioni Amplify alle dipendenze del progetto. Apri il file Podfile e aggiungi la riga con AmplifyPlugins/AWSCognitoAuthPlugin oppure copia e incolla l'intero file seguente

    # you need at least version 13.0 for this tutorial, more recent versions are valid too
    platform :ios, '13.0'
    
    target 'getting started' do
      # Comment the next line if you don't want to use dynamic frameworks
      use_frameworks!
    
      # Pods for getting started
      pod 'Amplify', '~> 1.0'                             # required amplify dependency
      pod 'Amplify/Tools', '~> 1.0'                       # allows to call amplify CLI from within Xcode
    
      pod 'AmplifyPlugins/AWSCognitoAuthPlugin', '~> 1.0' # support for Cognito user authentication
    
    end

    In un terminale, esegui il comando:

    pod install

    Il completamento del comando richiede alcuni secondi. Dovresti vedere quello che segue (il numero effettivo della versione potrebbe variare):

    Analyzing dependencies
    Downloading dependencies
    Installing AWSAuthCore (2.14.1)
    Installing AWSCognitoIdentityProvider (2.14.1)
    Installing AWSCognitoIdentityProviderASF (1.0.1)
    Installing AWSCore (2.14.1)
    Installing AWSMobileClient (2.14.1)
    Installing AWSPluginsCore (1.0.4)
    Installing AmplifyPlugins (1.0.4)
    Generating Pods project
    Integrating client project
    Pod installation complete! There are 3 dependencies from the Podfile and 8 total pods installed.
  • Torna a Xcode e apri il file Backend.swift. Nella classe Backend,

    • aggiungi un'istruzione di importazione per AmplifyPlugins
    • aggiungi una riga al codice di inizializzazione Amplify aggiunto nella sezione precedente.

    Il blocco di codice completo dovrebbe avere il seguente aspetto:

    // at the top of the file
    import AmplifyPlugins
    
    private init () {
      // initialize amplify
      do {
         try Amplify.add(plugin: AWSCognitoAuthPlugin())
         try Amplify.configure()
         print("Initialized Amplify")
      } catch {
         print("Could not initialize Amplify: \(error)")
      }
    }

    Per verificare che tutto funzioni come previsto, crea il progetto. Fai clic sul menu Product (Prodotto) e seleziona Build (Crea) o digita ⌘B. Non dovrebbero essere restituiti errori.

  • La modifica al codice restante traccia lo stato dell'utente (ha eseguito l'accesso oppure no?) e avvia l'interfaccia utente di accesso o registrazione se l'utente non ha eseguito l'accesso. 

    a. Aggiungi codice di accesso e di disconnessione. Aggiungi i seguenti tre metodi in un punto qualsiasi della classe Backend:

     

    // MARK: - User Authentication
    
    // signin with Cognito web user interface
    public func signIn() {
    
        _ = Amplify.Auth.signInWithWebUI(presentationAnchor: UIApplication.shared.windows.first!) { result in
            switch result {
            case .success(_):
                print("Sign in succeeded")
            case .failure(let error):
                print("Sign in failed \(error)")
            }
        }
    }
    
    // signout
    public func signOut() {
    
        _ = Amplify.Auth.signOut() { (result) in
            switch result {
            case .success:
                print("Successfully signed out")
            case .failure(let error):
                print("Sign out failed with error \(error)")
            }
        }
    }
    
    // change our internal state, this triggers an UI update on the main thread
    func updateUserData(withSignInStatus status : Bool) {
        DispatchQueue.main.async() {
            let userData : UserData = .shared
            userData.isSignedIn = status
        }
    }

    b. Aggiunta di un listener dell'hub di autenticazione

    Per tenere traccia delle modifiche dello stato di autenticazione, aggiungiamo il codice per effettuare l'iscrizione agli eventi di autenticazione inviati da Amplify. Inizializziamo l'hub nel metodo Backend.init().

    Quando si riceve un evento di autenticazione, chiamiamo il metodo updateUserData(). Questo metodo mantiene sincronizzato l'oggetto UserData. La proprietà UserData.isSignedIn è @Published, il che significa che l'interfaccia utente viene aggiornata automaticamente quando si modifica il valore. 

    Inoltre, aggiungiamo il codice per controllare lo stato di autenticazione precedente al momento dell'avvio dell'applicazione. All'avvio dell'applicazione, controlla se esista già una sessione Cognito e aggiorna l'interfaccia utente di conseguenza.

    In Backend.init(), aggiungi il seguente codice dopo l'inizializzazione di Amplify:

    // in private init() function
    // listen to auth events.
    // see https://github.com/aws-amplify/amplify-ios/blob/master/Amplify/Categories/Auth/Models/AuthEventName.swift
    _ = Amplify.Hub.listen(to: .auth) { (payload) in
    
        switch payload.eventName {
    
        case HubPayload.EventName.Auth.signedIn:
            print("==HUB== User signed In, update UI")
            self.updateUserData(withSignInStatus: true)
    
        case HubPayload.EventName.Auth.signedOut:
            print("==HUB== User signed Out, update UI")
            self.updateUserData(withSignInStatus: false)
    
        case HubPayload.EventName.Auth.sessionExpired:
            print("==HUB== Session expired, show sign in UI")
            self.updateUserData(withSignInStatus: false)
    
        default:
            //print("==HUB== \(payload)")
            break
        }
    }
     
    // let's check if user is signedIn or not
     _ = Amplify.Auth.fetchAuthSession { (result) in
         do {
             let session = try result.get()
                    
    // let's update UserData and the UI
         self.updateUserData(withSignInStatus: session.isSignedIn)
                    
         } catch {
              print("Fetch auth session failed with error - \(error)")
        }
    }    

    c. Aggiornamento del codice dell'interfaccia utente

    L'ultima modifica del codice è relativa all'interfaccia utente: aggiungiamo una ZStack alla ContentView. A seconda del valore di UserData.isSignedIn, l'interfaccia utente mostra un SigninButton o la visualizzazione elenco principale.

    Apri ContentView.swift e sostituisci il corpo nella struttura ContentView:

    var body: some View {
    
        ZStack {
            if (userData.isSignedIn) {
                NavigationView {
                    List {
                        ForEach(userData.notes) { note in
                            ListRow(note: note)
                        }
                    }
                    .navigationBarTitle(Text("Notes"))
                    .navigationBarItems(leading: SignOutButton())
                }
            } else {
                SignInButton()
            }
        }
    }

    Nello stesso file, aggiungi una visualizzazione SignInButton e SignOutButton:

    struct SignInButton: View {
        var body: some View {
            Button(action: { Backend.shared.signIn() }){
                HStack {
                    Image(systemName: "person.fill")
                        .scaleEffect(1.5)
                        .padding()
                    Text("Sign In")
                        .font(.largeTitle)
                }
                .padding()
                .foregroundColor(.white)
                .background(Color.green)
                .cornerRadius(30)
            }
        }
    }
    
    struct SignOutButton : View {
        var body: some View {
            Button(action: { Backend.shared.signOut() }) {
                    Text("Sign Out")
            }
        }
    }

    Per verificare che tutto funzioni come previsto, crea il progetto. Fai clic sul menu Product (Prodotto) e seleziona Build (Crea) o digita ⌘B. Non dovrebbero essere restituiti errori.

    d. Aggiornamento del file Info.plist

    Infine, dobbiamo garantire che l'applicazione venga avviata al termine della sequenza di autenticazione Web fornita dall'interfaccia utente in hosting Cognito. Aggiungiamo lo schema URI gettingstarted al file Info.plist dell'applicazione.

    In Xcode, seleziona il file Info.plist, fai clic su di esso con il tasto destro del mouse e seleziona Open As (Apri come), Source Code (Codice sorgente).

    Aggiungi i seguenti elementi <key> e <array> all'interno dell'elemento <dict> in alto.

    <plist version="1.0">
    
        <dict>
        <!-- YOUR OTHER PLIST ENTRIES HERE -->
    
        <!-- ADD AN ENTRY TO CFBundleURLTypes for Cognito Auth -->
        <!-- IF YOU DO NOT HAVE CFBundleURLTypes, YOU CAN COPY THE WHOLE BLOCK BELOW -->
        <key>CFBundleURLTypes</key>
        <array>
            <dict>
                <key>CFBundleURLSchemes</key>
                <array>
                    <string>gettingstarted</string>
                </array>
            </dict>
        </array>
    
        <!-- ... -->
        </dict>

    e. Creazione e test

    Per verificare che tutto funzioni come previsto, crea il progetto. Fai clic sul menu Product (Prodotto) e seleziona Run (Esegui) o digita ⌘R. Non dovrebbero essere restituiti errori. L'applicazione inizia nel pulsante di accesso.

    Ecco il flusso completo di registrazione:

Conclusione

Hai appena aggiunto l'autenticazione utente alla tua app con poche righe di codice! Nel prossimo modulo aggiungeremo un'API alla tua app.

Questo modulo è stato utile?

Aggiunta di un'API GraphQL e di un database