Introducción a AWS

Crear una aplicación Android

Crear una aplicación Android sencilla con AWS Amplify

Módulo 3: Agregar autenticación

En este módulo usará las CLI y bibliotecas de Amplify para configurar y agregar autenticación a su aplicación.

Introducción

La siguiente función que agregará es la autenticación de usuarios. En este módulo, aprenderá cómo autenticar un usuario con CLI y bibliotecas de Amplify, aprovechando Amazon Cognito, un proveedor de identidad de usuarios administrado.

También aprenderá a usar la interfaz de usuario alojada en Cognito para presentar un flujo completo de autenticación de usuarios, lo que permite a los usuarios registrarse, iniciar sesión y restablecer su contraseña con solo algunas líneas de código.

Utilizar una interfaz de usuarios alojada significa que la aplicación aprovecha las páginas web de Cognito para los flujos de interfaz de usuarios de registro e inicio de sesión. El usuario de la aplicación se redirige a una página web alojada en Cognito y se vuelve a dirigir a la aplicación después de registrarse. Por supuesto, Cognito y Amplify también admiten UI nativas y usted puede seguir estas instrucciones del taller para conocer más sobre la UI de autenticación personalizada.

Lo que aprenderá

  • Crear e implementar un servicio de autenticación
  • Configurar su aplicación Android para que incluya la autenticación de UI alojada en Cognito

Conceptos clave

Bibliotecas de Amplify: las bibliotecas de Amplify le permiten interactuar con los servicios de AWS desde una aplicación web o móvil.

Autenticación: en software, la autenticación es el proceso de verificar y administrar la identidad de un usuario mediante un servicio de autenticación o API.

 Tiempo de realización

10 minutos

 Servicios utilizados

Implementación

  • Crear el servicio de autenticación

    Para crear el servicio de autenticación, abra una terminal y ejecute este 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

    Sabrá que la conexión es exitosa cuando visualice este mensaje (el nombre exacto del recurso puede variar):

    Successfully added resource androidgettingstartedfc5a4717 locally
  • Implementar el servicio de autenticación

    Ahora que se ha configurado el servicio de autenticación en forma local, podemos implementarlo en la nube. En una terminal, ejecute este comando es su directorio del proyecto:

    amplify push
    
    # press Y when asked to continue

    Luego de un momento, debería ver el siguiente mensaje:

    ✔ All resources are updated in the cloud
    
    Hosted UI Endpoint: https://androidgettingstarted-dev.auth.eu-central-1.amazoncognito.com/
    Test Your Hosted UI Endpoint: https://androidgettingstarted-dev.auth.eu-central-1.amazoncognito.com/login?response_type=code&client_id=1234567890&redirect_uri=gettingstarted://
  • Agregar la biblioteca de autenticación de Amplify al proyecto

    Antes de ir al código, regrese a Android Studio y agregue la siguiente dependencia a `build.gradle` de su módulo junto con las otras implementaciones `amplifyframework` que agregó anteriormente y haga clic en Sync Now (Sincronizar ahora) cuando se le solicite.

    dependencies {
        ...
        // Amplify core dependency
        implementation 'com.amplifyframework:core:1.4.0'
        implementation 'com.amplifyframework:aws-auth-cognito:1.4.0'
    }
  • Configurar la biblioteca de autenticación de Amplify en el tiempo de ejecución

    Regrese a Android Studio, abra el archivo Backend.kt. En la clase Backend, agregue una línea al código de inicio de Amplify que agregamos en la sección anterior [en el método initialize()].

    El bloque de código completo debería verse así:

    // inside Backend class
    fun initialize(applicationContext: Context) : Backend {
        try {
            Amplify.addPlugin(AWSCognitoAuthPlugin())
            Amplify.configure(applicationContext)
    
            Log.i(TAG, "Initialized Amplify")
        } catch (e: AmplifyException) {
            Log.e(TAG, "Could not initialize Amplify", e)
        }
        return this
    }

    No se olvide de agregar las instrucciones de importación, Android Studio hace esto automáticamente (en Mac haga clic en Alt + Intro en cada error que detecte el editor de código).

    Como en el paso anterior, agregue la instrucción de importación obligatoria para cada definición de clase faltante (Alt + Intro en las letras rojas).

    Para verificar que todo funcione como se espera, cree el proyecto. Haga clic en el menú Build (Crear) y seleccione Make Project (Crear proyecto) o, en Mac, presione ⌘F9. No debería haber ningún error.

  • Activar la autenticación en el tiempo de ejecución

    El código restante cambia los registros del estado de un usuario (¿iniciaron sesión o no?) y activa la interfaz de usuario de inicio de sesión o registro cuando el usuario hace clic en un ícono de candado.

    a. Agregar los métodos signIn y signOut
    En cualquier lugar en la clase Backend, agregue los siguientes cuatro métodos:
    private fun updateUserData(withSignedInStatus : Boolean) {
        UserData.setSignedIn(withSignedInStatus)
    }
    
    fun signOut() {
        Log.i(TAG, "Initiate Signout Sequence")
    
        Amplify.Auth.signOut(
            { Log.i(TAG, "Signed out!") },
            { error -> Log.e(TAG, error.toString()) }
        )
    }
    
    fun signIn(callingActivity: Activity) {
        Log.i(TAG, "Initiate Signin Sequence")
    
        Amplify.Auth.signInWithWebUI(
            callingActivity,
            { result: AuthSignInResult ->  Log.i(TAG, result.toString()) },
            { error: AuthException -> Log.e(TAG, error.toString()) }
        )
    }

    Luego, agregue las instrucciones de importación obligatorias para cada definición de clase faltante (Alt + Intro en las letras rojas). Cuando tiene una opción entre varias clases, asegúrese de seleccionar la del paquete de Amplify, así como se muestra en la captura de pantalla a continuación.

    AndroidAppTutorial_Modiule3_Image1

    Tenga en cuenta que no actualizamos el marcador UserData.isSignedIn de estos métodos, esto se realiza en la siguiente sección.

    b. Agregar un agente de escucha hub de autenticación

    A fin de seguir los cambios del estado de autenticación, agregamos un código para suscribir a los eventos de autenticación enviados por Amplify. Iniciamos el hub en el método Backend.initialize().

    Cuando se recibe un evento de autenticación, llamamos al método updateUserData(). Este método mantiene al objeto UserData en sincronización. La propiedad UserData.isSignedIn es un LiveData<Boolean>, quiere decir que, cuando los valores cambian, se notificarán a los observadores suscritos a esta propiedad. Utilizamos este mecanismo para actualizar la interfaz de usuario de manera automática. Puede obtener más información sobre LiveData en el documento de Android.

    También agregamos el código para comprobar el estado de autenticación previo al tiempo de inicio de la aplicación. Cuando la aplicación se inicia, comprueba si ya existe una sesión Cognito y, en consecuencia, actualiza el UserData.

    En Backend.initialize(), agregue el siguiente código después del bloque probar o capturar y antes de la instrucción de retorno.

    // in Backend.initialize() function, after the try/catch block but before the return statement 
    
    Log.i(TAG, "registering hub event")
    
    // listen to auth event
    Amplify.Hub.subscribe(HubChannel.AUTH) { hubEvent: HubEvent<*> ->
    
        when (hubEvent.name) {
            InitializationStatus.SUCCEEDED.toString() -> {
                Log.i(TAG, "Amplify successfully initialized")
            }
            InitializationStatus.FAILED.toString() -> {
                Log.i(TAG, "Amplify initialization failed")
            }
            else -> {
                when (AuthChannelEventName.valueOf(hubEvent.name)) {
                    AuthChannelEventName.SIGNED_IN -> {
                        updateUserData(true)
                        Log.i(TAG, "HUB : SIGNED_IN")
                    }
                    AuthChannelEventName.SIGNED_OUT -> {
                        updateUserData(false)
                        Log.i(TAG, "HUB : SIGNED_OUT")
                    }
                    else -> Log.i(TAG, """HUB EVENT:${hubEvent.name}""")
                }
            }
        }
    }
    
    Log.i(TAG, "retrieving session status")
    
    // is user already authenticated (from a previous execution) ?
    Amplify.Auth.fetchAuthSession(
        { result ->
            Log.i(TAG, result.toString())
            val cognitoAuthSession = result as AWSCognitoAuthSession
            // update UI
            this.updateUserData(cognitoAuthSession.isSignedIn)
            when (cognitoAuthSession.identityId.type) {
                AuthSessionResult.Type.SUCCESS ->  Log.i(TAG, "IdentityId: " + cognitoAuthSession.identityId.value)
                AuthSessionResult.Type.FAILURE -> Log.i(TAG, "IdentityId not present because: " + cognitoAuthSession.identityId.error.toString())
            }
        },
        { error -> Log.i(TAG, error.toString()) }
    )

    Para verificar que todo funcione como se espera, cree el proyecto. Haga clic en el menú Build (Crear) y seleccione Make Project (Crear proyecto) o, en Mac, presione ⌘F9. No debería haber ningún error.

    c. Actualizar el código de interfaz de usuario

    El último cambio en el código se relaciona a la interfaz de usuario, agregamos un FloatingActionButton a la actividad principal.

    En res/layout, abra activity_main.xml y reemplaceel FloatingActionButton existente con este:

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fabAuth"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@drawable/ic_baseline_lock"
        app:fabCustomSize="60dp"
        app:fabSize="auto"
        />

    Agregue un ícono de candado en res/drawable. Haga clic con el botón derecho en drawable (dibujable), seleccione New (Nuevo), luego Vector Asset (Activo de vector). Elija un ícono de candado desde imágenes prediseñadas y escriba ic_baseline_lock (sin el _24) como nombre y elija el ícono de candado cerrado desde imágenes prediseñadas. Haga clic en Next (Siguiente) y en Finish (Finalizar).

    Repita lo mismo con el ícono de candado abierto.

    AndroidAppTutorial_Modiule3_Image2
    AndroidAppTutorial_Modiule3_Image3

    Después de esto, debe tener los siguientes archivos en el directorio de elementos de diseño:

    AndroidAppTutorial_Modiule3_Image4

    Ahora, vincule el botón creado recientemente en el código. En java/com.example.androidgettingstarted/, abra MainActivity.kt y agregue el siguiente código.

    // anywhere in the MainActivity class
    private fun setupAuthButton(userData: UserData) {
    
        // register a click listener
        fabAuth.setOnClickListener { view ->
    
            val authButton = view as FloatingActionButton
    
            if (userData.isSignedIn.value!!) {
                authButton.setImageResource(R.drawable.ic_baseline_lock_open)
                Backend.signOut()
            } else {
                authButton.setImageResource(R.drawable.ic_baseline_lock_open)
                Backend.signIn(this)
            }
        }
    }

    Todavía en MainActivity, agregue el siguiente código al final del método onCreate():

    setupAuthButton(UserData)
    
    UserData.isSignedIn.observe(this, Observer<Boolean> { isSignedUp ->
        // update UI
        Log.i(TAG, "isSignedIn changed : $isSignedUp")
    
        if (isSignedUp) {
            fabAuth.setImageResource(R.drawable.ic_baseline_lock_open)
        } else {
            fabAuth.setImageResource(R.drawable.ic_baseline_lock)
        }
    })

    El código anterior registra un observador en el valor Userdata.isSignedIn. Se llama al cierre cuando el valor isSignedIn cambia. En este momento, cambiamos el ícono de candado: abierto cuando el usuario es autenticado y cerrado cuando no tiene sesión.

    Para verificar que todo funcione como se espera, cree el proyecto. Haga clic en el menú Build (Crear) y seleccione Make Project (Crear proyecto) o, en Mac, presione ⌘F9. No debería haber ningún error.

    d. Actualizar AndroidManifest.xml y MainActivity

    Por último, debemos garantizar que la aplicación se lance al final de la secuencia de autenticación web, proporcionada por la interfaz de usuario alojada en Cognito. Agregamos una nueva actividad en el archivo de manifiesto. Se llama a la actividad cuando se recibe el esquema URI gettingstarted.

    En Android Studio, en manifiestos, abra AndroidManifest.xml y agregue la siguiente actividad dentro del elemento de la aplicación.

        <activity
    android:name="com.amazonaws.mobileconnectors.cognitoauth.activities.CustomTabsRedirectActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
    
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
    
                <data android:scheme="gettingstarted" />
            </intent-filter>
        </activity>
    

    En java/com.example.androidgettingstarted/, abra MainActivity.kt y agregue el siguiente código en cualquier lugar de la clase.

    // MainActivity.kt
    // receive the web redirect after authentication
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        Backend.handleWebUISignInResponse(requestCode, resultCode, data)
    }

    En java/com.example.androidgettingstarted/, abra Backend.kt y agregue el siguiente código en cualquier lugar de la clase.

    // Backend.kt
    // pass the data from web redirect to Amplify libs 
    fun handleWebUISignInResponse(requestCode: Int, resultCode: Int, data: Intent?) {
        Log.d(TAG, "received requestCode : $requestCode and resultCode : $resultCode")
        if (requestCode == AWSCognitoAuthPlugin.WEB_UI_SIGN_IN_ACTIVITY_CODE) {
            Amplify.Auth.handleWebUISignInResponse(data)
        }
    }

    e. Crear y probar

    Para verificar que todo funcione como se espera, cree y ejecute el proyecto. Haga clic en el icono Run (Ejecutar) ▶️️ en la barra de herramientas o escriba ^ R. No debería haber ningún error. La aplicación se inicia y hay un botón flotante de candado cerrado en la parte inferior derecha de la pantalla.

    Este es el flujo de registro completo.

    AndroidAppTutorial_Modiule3_Image5
    AndroidAppTutorial_Modiule3_Image6
    AndroidAppTutorial_Modiule3_Image7
    AndroidAppTutorial_Modiule3_Image8
    AndroidAppTutorial_Modiule3_Image9

Conclusión

Ahora ha agregado la autenticación del usuario a su aplicación con solo algunas líneas de código. En el siguiente módulo, agregaremos una API a su aplicación.

¿Este módulo le resultó útil?

Gracias
Indíquenos lo que le gustó.
Cerrar
Lamentamos haberlo decepcionado
¿Hay información desactualizada, confusa o inexacta? Ayúdenos a mejorar este tutorial con sus comentarios.
Cerrar

Agregar una API de GraphQL y una base de datos