Adicionar autenticação ao aplicativo do Android

Resumo

Neste tutorial, você adiciona autenticação ao projeto de início rápido da lista de tarefas pendentes no Android usando um provedor de identidade com suporte. Este tutorial se baseia no tutorial Introdução aos Aplicativos Móveis , que você deve concluir primeiro.

Registrar seu aplicativo para autenticação e configurar o Serviço de Aplicativo do Azure

Primeiro, é necessário registrar seu aplicativo em um site do provedor de identidade. Em seguida, você definirá as credenciais geradas pelo provedor no back-end dos Aplicativos Móveis.

  1. Configure o provedor de identidade preferido, seguindo as instruções específicas do provedor:

  2. Repita as etapas anteriores para cada provedor ao qual você desejar dar suporte em seu aplicativo.

Adicionar seu aplicativo às URLs de redirecionamento externo permitidas

A autenticação segura exige que você defina um novo esquema de URL para seu aplicativo. Isso permite que o sistema de autenticação redirecione para seu aplicativo após a conclusão do processo de autenticação. Neste tutorial, usamos sempre o esquema de URL appname. No entanto, você pode usar o esquema de URL que quiser. Ele deve ser exclusivo para seu aplicativo móvel. Para habilitar o redirecionamento no lado do servidor:

  1. No Portal do Azure, selecione seu Serviço de Aplicativo.

  2. Clique na opção de menu Autenticação/Autorização.

  3. Em URLs de Redirecionamento Externo Permitidas, insira appname://easyauth.callback. O appname na cadeia de caracteres é o esquema de URL para seu aplicativo móvel. Ele deve seguir as especificações de URL normal para um protocolo (use somente letras e números e inicie com uma letra). Você deve anotar a cadeia de caracteres escolhida, já que precisará ajustar o código do aplicativo móvel com o esquema de URL em vários lugares.

  4. Clique em OK.

  5. Clique em Save (Salvar).

Restringir permissões a usuários autenticados

Por padrão, APIs em um back-end de Aplicativos Móveis podem ser chamadas de forma anônima. Em seguida, você precisa restringir o acesso somente aos clientes autenticados.

  • Back-end do Node.js (por meio do portal do Azure) :

    Nas configurações de seus Aplicativos Móveis, clique em Tabelas Fáceis e selecione a tabela. Clique em Alterar permissões, selecione Apenas acesso autenticado para todas as permissões e clique em Salvar.

  • Back-end do .NET (C#):

    No projeto do servidor, navegue até controladores>TodoItemController. cs. Adicione o atributo [Authorize] à classe TodoItemController , como a seguir. Para restringir o acesso somente aos métodos específicos, você também pode aplicar esse atributo apenas aos métodos, em vez de à classe. Republicar o projeto de servidor.

      [Authorize]
      public class TodoItemController : TableController<TodoItem>
    
  • Back-end do Node.js (por meio de código Node.js) :

    Para exigir autenticação para acesso à tabela, adicione a seguinte linha ao script de servidor Node.js:

      table.access = 'authenticated';
    

    Para obter mais detalhes, veja Como exigir autenticação para acesso às tabelas. Para saber como baixar o projeto de código de início rápido do seu site, consulte Como baixar o projeto de código de início rápido de back-end do Node.js usando Git.

  • No Android Studio, abra o projeto concluído com o tutorial Introdução aos Aplicativos Móveis. No menu Executar, clique em Executar aplicativo e verifique se uma exceção sem tratamento com um código de status 401 (Não autorizado) é acionada depois que o aplicativo é iniciado.

    Essa exceção ocorre porque o aplicativo tenta acessar o back-end como um usuário não autenticado, mas a tabela TodoItem agora exige autenticação.

Em seguida, você atualiza o aplicativo para autenticar os usuários antes de solicitar recursos do back-end dos Aplicativos Móveis.

Adicionar autenticação ao aplicativo

  1. Abra o projeto no Android Studio.

  2. No Gerenciador de Projetos, no Android Studio, abra o arquivo ToDoActivity.java e adicione as seguintes instruções de importação:

    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.atomic.AtomicBoolean;
    
    import android.content.Context;
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.Editor;
    
    import com.microsoft.windowsazure.mobileservices.authentication.MobileServiceAuthenticationProvider;
    import com.microsoft.windowsazure.mobileservices.authentication.MobileServiceUser;
    
  3. Adicione o seguinte método à classe ToDoActivity :

    // You can choose any unique number here to differentiate auth providers from each other. Note this is the same code at login() and onActivityResult().
    public static final int GOOGLE_LOGIN_REQUEST_CODE = 1;
    
    private void authenticate() {
        // Sign in using the Google provider.
        mClient.login(MobileServiceAuthenticationProvider.Google, "{url_scheme_of_your_app}", GOOGLE_LOGIN_REQUEST_CODE);
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // When request completes
        if (resultCode == RESULT_OK) {
            // Check the request code matches the one we send in the login request
            if (requestCode == GOOGLE_LOGIN_REQUEST_CODE) {
                MobileServiceActivityResult result = mClient.onActivityResult(data);
                if (result.isLoggedIn()) {
                    // sign-in succeeded
                    createAndShowDialog(String.format("You are now signed in - %1$2s", mClient.getCurrentUser().getUserId()), "Success");
                    createTable();
                } else {
                    // sign-in failed, check the error message
                    String errorMessage = result.getErrorMessage();
                    createAndShowDialog(errorMessage, "Error");
                }
            }
        }
    }
    

    Esse código cria um novo método para manipular o processo de autenticação. Um diálogo exibe a ID do usuário autenticado. Você só pode continuar em uma autenticação bem-sucedida.

    Observação

    Se você estiver usando um provedor de identidade diferente do Google, altere o valor passado ao método login para um dos valores a seguir: MicrosoftAccount, Facebook, Twitter ou windowsazureactivedirectory.

  4. No método OnCreate, adicione a linha de código a seguir após o código que cria uma instância do objeto MobileServiceClient.

    authenticate();
    

    Essa chamada inicia o processo de autenticação.

  5. Mova o código restante para depois authenticate(); no método OnCreate para um novo método CreateTable :

    private void createTable() {
    
        // Get the table instance to use.
        mToDoTable = mClient.getTable(ToDoItem.class);
    
        mTextNewToDo = (EditText) findViewById(R.id.textNewToDo);
    
        // Create an adapter to bind the items with the view.
        mAdapter = new ToDoItemAdapter(this, R.layout.row_list_to_do);
        ListView listViewToDo = (ListView) findViewById(R.id.listViewToDo);
        listViewToDo.setAdapter(mAdapter);
    
        // Load the items from Azure.
        refreshItemsFromTable();
    }
    
  6. Para garantir que o redirecionamento funcione conforme o esperado, adicione o seguinte snippet de RedirectUrlActivity a AndroidManifest.xml:

    <activity android:name="com.microsoft.windowsazure.mobileservices.authentication.RedirectUrlActivity">
        <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="{url_scheme_of_your_app}"
                android:host="easyauth.callback"/>
        </intent-filter>
    </activity>
    
  7. Adicione redirectUriScheme a build.gradle do seu aplicativo Android.

    android {
        buildTypes {
            release {
                // ...
                manifestPlaceholders = ['redirectUriScheme': '{url_scheme_of_your_app}://easyauth.callback']
            }
            debug {
                // ...
                manifestPlaceholders = ['redirectUriScheme': '{url_scheme_of_your_app}://easyauth.callback']
            }
        }
    }
    
  8. Adicione com.android.support:customtabs:23.0.1 às dependências em seu build.gradle:

    dependencies {
        // ...
        compile 'com.android.support:customtabs:23.0.1'
    }
    
  9. No menu Executar, clique em Executar aplicativo para iniciar o aplicativo e entrar com seu provedor de identidade escolhido.

Aviso

O esquema de URL mencionado diferencia maiúsculas de minúsculas. Certifique-se de que todas as ocorrências de {url_scheme_of_you_app} a mesma formatação, maiúsculas ou minúsculas.

Ao entrar com êxito, o aplicativo deve ser executado sem erros e você deve ser capaz de consultar o serviço de back-end e fazer atualizações nos dados.

Armazenar em cache tokens de autenticação no cliente

O exemplo anterior mostrou um logon padrão, que requer que o cliente contate o provedor de identidade e o serviço de back-end do Azure sempre que o aplicativo for iniciado. Esse método é ineficiente e você pode ter problemas relacionados ao uso caso muitos clientes tentem iniciar o aplicativo simultaneamente. Uma abordagem melhor é armazenar em cache o token de autorização retornado pelo serviço do Azure e tentar usá-lo antes de usar um logon baseado em provedor.

Observação

Você pode armazenar em cache o token emitido pelo serviço de back-end do Azure usando tanto a autenticação gerenciada pelo cliente quanto a autenticação gerenciada pelo serviço. Este tutorial usa a autenticação gerenciada pelo serviço.

  1. Abra o arquivo ToDoActivity.java e adicione as seguintes instruções de importação:

    import android.content.Context;
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.Editor;
    
  2. Adicione os seguintes membros à classe ToDoActivity :

    public static final String SHAREDPREFFILE = "temp";
    public static final String USERIDPREF = "uid";
    public static final String TOKENPREF = "tkn";
    
  3. No arquivo ToDoActivity.java, adicione a seguinte definição para o método cacheUserToken.

    private void cacheUserToken(MobileServiceUser user)
    {
        SharedPreferences prefs = getSharedPreferences(SHAREDPREFFILE, Context.MODE_PRIVATE);
        Editor editor = prefs.edit();
        editor.putString(USERIDPREF, user.getUserId());
        editor.putString(TOKENPREF, user.getAuthenticationToken());
        editor.commit();
    }
    

    Este método armazena a ID e o token do usuário em um arquivo preferencial marcado como privado. Isto deve proteger o acesso ao cache para que os outros aplicativos do dispositivo não tenham acesso ao token. A preferência é uma área restrita para o aplicativo. No entanto, se alguém obtiver acesso ao dispositivo, é possível que a pessoa ganhe acesso ao cache de token de outras formas.

    Observação

    Você pode proteger ainda mais o token com criptografia se o acesso do token a seus dados for considerado altamente confidencial e alguém puder acessar o dispositivo. No entanto, uma solução completamente segura está além do escopo deste tutorial e depende dos seus requisitos de segurança.

  4. No arquivo ToDoActivity.java, adicione a seguinte definição para o método loadUserTokenCache.

    private boolean loadUserTokenCache(MobileServiceClient client)
    {
        SharedPreferences prefs = getSharedPreferences(SHAREDPREFFILE, Context.MODE_PRIVATE);
        String userId = prefs.getString(USERIDPREF, null);
        if (userId == null)
            return false;
        String token = prefs.getString(TOKENPREF, null);
        if (token == null)
            return false;
    
        MobileServiceUser user = new MobileServiceUser(userId);
        user.setAuthenticationToken(token);
        client.setCurrentUser(user);
    
        return true;
    }
    
  5. No arquivo ToDoActivity.java, substitua os métodos authenticate e onActivityResult pelos seguintes métodos, que usam um cache de token. Altere o provedor de logon se quiser usar uma conta que não seja do Google.

    private void authenticate() {
        // We first try to load a token cache if one exists.
        if (loadUserTokenCache(mClient))
        {
            createTable();
        }
        // If we failed to load a token cache, sign in and create a token cache
        else
        {
            // Sign in using the Google provider.
            mClient.login(MobileServiceAuthenticationProvider.Google, "{url_scheme_of_your_app}", GOOGLE_LOGIN_REQUEST_CODE);
        }
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // When request completes
        if (resultCode == RESULT_OK) {
            // Check the request code matches the one we send in the sign-in request
            if (requestCode == GOOGLE_LOGIN_REQUEST_CODE) {
                MobileServiceActivityResult result = mClient.onActivityResult(data);
                if (result.isLoggedIn()) {
                    // sign-in succeeded
                    createAndShowDialog(String.format("You are now signed in - %1$2s", mClient.getCurrentUser().getUserId()), "Success");
                    cacheUserToken(mClient.getCurrentUser());
                    createTable();
                } else {
                    // sign-in failed, check the error message
                    String errorMessage = result.getErrorMessage();
                    createAndShowDialog(errorMessage, "Error");
                }
            }
        }
    }
    
  6. Compile o aplicativo e teste a autenticação usando uma conta válida. Execute pelo menos uma vez. Durante a primeira execução, você deverá ser solicitado a iniciar uma sessão e criar o cache do token. Depois disso, cada execução tentará carregar o cache de token para autenticação. Não deve ser solicitado que você inicie uma sessão.

Próximas etapas

Agora que você concluiu este tutorial de autenticação básica, considere continuar com um dos seguintes tutoriais: