Conceitos básicos da AWS

Criar uma aplicação Android

Criar uma aplicação Android simples usando o AWS Amplify

Módulo 3: adicionar autenticação

Neste módulo, você usará as bibliotecas e a CLI do Amplify para configurar e adicionar autenticação a seu aplicativo.

Introdução

O próximo recurso a ser adicionado é a autenticação do usuário. Neste módulo, você aprenderá como autenticar um usuário com as bibliotecas e a CLI do Amplify utilizando o Amazon Cognito, um provedor de identidade de usuários gerenciado.

Você aprenderá também como usar a Interface de usuário hospedada no Cognito para apresentar todo o fluxo de autenticação de um usuário, permitindo que os usuários se cadastrem, façam login e redefinam as senhas com apenas algumas linhas de código.

Usar uma "Interface de usuário hospedada" significa que a aplicação aproveita as páginas da web do Cognito para os fluxos de interface do usuário de login e cadastro. O usuário do aplicativo é redirecionado para uma página da Web hospedada pelo Cognito e redirecionado de volta para o aplicativo após o login. Obviamente, o Cognito e o Amplify também oferecem suporte à IU nativa, e você pode seguir as instruções deste workshop para saber mais sobre a IU de autenticação personalizada.

O que você aprenderá

  • Criar e implantar um serviço de autenticação
  • Configurar seu aplicativo Android para incluir a autenticação de IU hospedada pelo Cognito

Conceitos principais

Bibliotecas do Amplify – As bibliotecas do Amplify permitem interagir com os serviços da AWS de uma aplicação móvel ou Web.

Autenticação – Em software, autenticação é o processo de verificação e gerenciamento da identidade de um usuário, usando um serviço de autenticação ou API.

 Tempo para a conclusão

10 minutos

 Serviços usados

Implementação

  • Criar o serviço de autenticação

    Para criar o serviço de autenticação, abra um terminal e execute 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

    Você saberá que a configuração teve êxito quando vir esta mensagem (o nome exato do recurso pode variar):

    Successfully added resource androidgettingstartedfc5a4717 locally
  • Implantar o serviço de autenticação

    Agora que o serviço de autenticação foi configurado localmente, podemos implantá-lo na nuvem. Em um terminal, execute este comando no diretório do seu projeto:

    amplify push
    
    # press Y when asked to continue

    Depois de um tempo, você verá a seguinte mensagem:

    ✔ 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://
  • Adicionar biblioteca de autenticação do Amplify ao projeto

    Antes de ir para o código, volte ao Android Studio, adicione a seguinte dependência ao `build.gradle` do seu módulo com outras implementações de `amplifyframework` que você adicionou anteriormente e clique em Sync Now (Sincronizar agora) quando solicitado:

    dependencies {
        ...
        // Amplify core dependency
        implementation 'com.amplifyframework:core:1.4.0'
        implementation 'com.amplifyframework:aws-auth-cognito:1.4.0'
    }
  • Configurar a biblioteca de autenticação do Amplify em tempo de execução

    De volta ao Android Studio, abra o arquivo Backend.kt. Na classe Backend, adicione uma linha ao código de inicialização do Amplify que adicionamos na seção anterior (no método initialize()).

    Aparência do bloco de códigos completo:

    // 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
    }

    Não se esqueça de adicionar as declarações de importação; o Android Studio faz isso para você automaticamente (no Mac, clique em Alt + Enter em cada erro detectado pelo editor de código).

    Como na etapa anterior, adicione as instruções de importação necessárias para cada definição de classe ausente (Alt + Enter nas palavras em vermelho).

    Para verificar se tudo funciona conforme o esperado, compile o projeto. Clique no menu Build (Compilar) e selecione Make Project (Criar projeto) ou, no Mac, digite ⌘F9. Não deve aparecer nenhum erro.

  • Acionar autenticação em tempo de execução

    A mudança restante do código rastreia o status de um usuário (se ele está ou não conectado) e aciona a interface de usuário de login/cadastro quando o usuário clica em um ícone de cadeado.

    a. Adicionar métodos signIn e signOut
    Em qualquer lugar da classe de back-end, adicione estes quatro 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()) }
        )
    }

    Em seguida, adicione as instruções de importação necessárias para cada definição de classe ausente (Alt + Enter nas palavras em vermelho). Quando você precisar escolher entre diversas classes, lembre-se de escolher uma no pacote do Amplify, como mostra a captura de tela abaixo.

    AndroidAppTutorial_Modiule3_Image1

    Observe que não atualizamos o sinalizador UserData.isSignedIn com esses métodos; isso será feito na próxima seção.

    b. Adicionar um listener de hub de autenticação

    Para acompanhar as alterações no status de autenticação, adicionamos código para assinar os eventos de autenticação enviados pelo Amplify. Iniciamos o hub no método Backend.initialize().

    Quando um evento de autenticação é recebido, chamamos o método updateUserData(). Esse método mantém o objeto UserData sincronizado. A propriedade UserData.isSignedIn é um LiveData<Boolean>, o que significa que observadores inscritos nessa propriedade serão notificados quando o valor mudar. Usaremos esse mecanismo para atualizar a interface de usuário automaticamente. Você pode obter mais informações sobre o LiveData no documento do Android.

    Também adicionamos código para verificar o status de autenticação anterior no tempo de inicialização da aplicação. Quando a aplicação é iniciada, ela verifica se já existe uma sessão do Cognito e atualiza o UserData conforme adequado.

    Em Backend.initialize(), adicione o código abaixo após o bloco try/catch e antes da instrução return.

    // 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 se tudo funciona conforme o esperado, compile o projeto. Clique no menu Build (Compilar) e selecione Make Project (Criar projeto) ou, no Mac, digite ⌘F9. Não deve aparecer nenhum erro.

    c. Atualizar o código de interface de usuário

    A última mudança no código está relacionada à interface de usuário, quando adicionamos um FloatingActionButton à atividade principal.

    Em res/layout, abra activity_main.xml e substitua o FloatingActionButton existente por 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"
        />

    Adicione um ícone de cadeado em res/drawable. Clique com o botão direito em drawable, selecione New (Novo) e depois Vector Asset (Ativo de vetor). Escolha o ícone de cadeado no Clip-art e insira ic_baseline_lock (sem o _24) como o nome e escolha o ícone de cadeado fechado no Clip-art. Clique em Next (Avançar) e em Finish (Concluir).

    Repita o mesmo processo com o ícone de cadeado aberto.

    AndroidAppTutorial_Modiule3_Image2
    AndroidAppTutorial_Modiule3_Image3

    Depois disso, você deve ter os seguintes arquivos no seu diretório drawable:

    AndroidAppTutorial_Modiule3_Image4

    Agora vincule o botão recém-criado no código. Em java/com.example.androidgettingstarted/, abra MainActivity.kt e adicione o seguinte 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)
            }
        }
    }

    Ainda em MainActivity, adicione o código abaixo no final do 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)
        }
    })

    O código acima registra um observador no valor Userdata.isSignedIn. O closure é chamado quando o valor de isSignedIn muda. No momento, só alteramos o ícone de cadeado: aberto quando o usuário está autenticado e fechado quando não há sessão em curso.

    Para verificar se tudo funciona conforme o esperado, compile o projeto. Clique no menu Build (Compilar) e selecione Make Project (Criar projeto) ou, no Mac, digite ⌘F9. Não deve aparecer nenhum erro.

    d. Atualizar AndroidManifest.xml e MainActivity

    Por fim, precisamos assegurar que nosso aplicativo seja iniciado no final da sequência de autenticação da Web, fornecida pela interface de usuário hospedada pelo Cognito. Adicionamos uma atividade nova no arquivo manifesto. A atividade é chamada quando o esquema gettingstarted URI é recebido.

    No Android Studio, em manifests (manifestos), abra AndroidManifest.xml e adicione a atividade abaixo dentro do elemento application.

        <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>
    

    Em java/com.example.androidgettingstarted/, abra MainActivity.kt e adicione o seguinte código em qualquer lugar da classe.

    // 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)
    }

    Em java/com.example.androidgettingstarted/, abra Backend.kt e adicione o seguinte código em qualquer lugar da classe.

    // 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. Compilar e testar

    Para verificar se tudo funciona conforme o esperado, compile e execute o projeto. Clique no ícone Run (Executar) ▶️ na barra de ferramentas ou digite ^ R. Não deve aparecer nenhum erro. O aplicativo é iniciado e há um botão flutuante de cadeado fechado no lado direito inferior da tela.

    Este é o fluxo completo de cadastro.

    AndroidAppTutorial_Modiule3_Image5
    AndroidAppTutorial_Modiule3_Image6
    AndroidAppTutorial_Modiule3_Image7
    AndroidAppTutorial_Modiule3_Image8
    AndroidAppTutorial_Modiule3_Image9

Conclusão

Você acaba de adicionar a autenticação de usuários ao seu aplicativo, com apenas algumas linhas de código! No próximo módulo, adicionaremos uma API ao aplicativo.

Este módulo foi útil?

Agradecemos a sua atenção
Gostaríamos de saber do que você gostou.
Fechar
Desculpe por ter desapontado
Encontrou algo desatualizado, confuso ou incorreto? Envie seus comentários para nos ajudar a melhorar este tutorial.
Fechar

Adicionar API GraphQL e banco de dados