Como armazenar com segurança o token e o segredo de acesso no Android?

123

Vou usar o outh para buscar e-mails e contatos do google. Não quero pedir ao usuário que faça login para obter um token de acesso e um segredo. Pelo que entendi, preciso armazená-los com meu aplicativo em um banco de dados ou SharedPreferences. Mas estou um pouco preocupado com os aspectos de segurança com isso. Eu li que você pode criptografar e descriptografar os tokens, mas é fácil para um invasor descompilar seu apk e classes e obter a chave de criptografia.
Qual é o melhor método para armazenar com segurança esses tokens no Android?

sim cara
fonte
1
Como guardo a chave e o segredo do consumidor (não é seguro protegê-los)? Eu preciso deles para solicitar o accesstoken e secret .. como os outros aplicativos existentes usando oauth fazem isso? hmm finalmente com oauth, você precisa cuidar de muito mais problemas de segurança para mim .... preciso manter o token / segredo do consumidor em segurança e também o token e segredo de acesso .... finalmente não seria mais simples apenas armazene o nome de usuário / senha do usuário criptografado? ... no final, o último não é melhor? Eu ainda não consigo ver como oauth é melhor ...
yeahman
você pode me dizer .. qual arquivo armazena o token de acesso? Eu sou novo para android e eu tentei correr amostra mais app.But eu não encontrar isso em qualquer lugar [método GoogleAuthUtil.getToken ().]
Abhishek Kaushik

Respostas:

118

Armazene-os como preferências compartilhadas . Por padrão, são privados e outros aplicativos não podem acessá-los. Em dispositivos com raiz, se o usuário permitir explicitamente o acesso a algum aplicativo que esteja tentando lê-los, o aplicativo poderá usá-los, mas você não poderá se proteger. Quanto à criptografia, você precisa exigir que o usuário insira a frase secreta descriptografada todas as vezes (anulando o objetivo de armazenar em cache as credenciais) ou salve a chave em um arquivo e o mesmo problema ocorrerá.

Existem alguns benefícios em armazenar tokens em vez da senha real do nome de usuário:

  • Aplicativos de terceiros não precisam saber a senha e o usuário pode ter certeza de que a envia apenas para o site original (Facebook, Twitter, Gmail, etc.)
  • Mesmo que alguém roube um token, ele não consegue ver a senha (que o usuário também pode estar usando em outros sites)
  • Os tokens geralmente têm uma vida útil e expiram após um certo tempo
  • Os tokens podem ser revogados se você suspeitar que eles foram comprometidos
Nikolay Elenkov
fonte
1
thx pela resposta! mas como posso saber se minha chave do consumidor foi comprometida? lol, será difícil dizer .. ok sobre como armazenar o token de acesso e o segredo, ok eu os salvo em preferências compartilhadas e criptografá-los, mas e a chave e o segredo do consumidor? Não posso armazená-los em preferências compartilhadas (eu precisaria escrever explicitamente a chave e o segredo do consumidor no código para salvá-lo em preferência compartilhada em primeiro lugar) .. não sei se você entende o que quero dizer.
yeahman
2
Você deve colocar o aplicativo de uma maneira (um pouco) ofuscada, para que eles não fiquem imediatamente visíveis após a descompilação ou usar seu próprio webapp de proxy de autenticação que possui a chave e o segredo. Colocá-los no aplicativo é obviamente mais fácil e, se você acha que o risco de alguém tentar quebrar seu aplicativo é suficientemente baixo, siga essa abordagem. BTW, os pontos acima são para a senha do usuário. Se você descobrir que sua chave / segredo de consumidor foi comprometida, também poderá revogá-las (isso, obviamente, interromperá seu aplicativo).
Nikolay Elenkov
1
@NikolayElenkov: Você escreveu 'Quanto à criptografia, você precisa exigir que o usuário insira a senha descriptografada todas as vezes (derrotando assim o objetivo de armazenar credenciais em cache) ou salve a chave em um arquivo e você terá o mesmo problema'. . E se os crackers inverterem seu aplicativo para obter informações sobre como a criptografia funciona? Sua defesa pode estar quebrada. É uma prática recomendada armazenar essas informações (token, criptografia ...) usando código nativo?
Anhldbk
1
Se os dados do aplicativo forem limpos, o token de atualização será perdido, o que provavelmente não é o que o usuário queria.
Rds
1
Essa não é a melhor maneira de armazenar tokens hoje em dia!
Rahul Rastogi 01/02/19
19

Você pode armazená-los no AccountManager . É considerado uma boa prática de acordo com esses caras.

insira a descrição da imagem aqui

Aqui está a definição oficial:

Esta classe fornece acesso a um registro centralizado das contas online do usuário. O usuário insere credenciais (nome de usuário e senha) uma vez por conta, concedendo aos aplicativos acesso a recursos online com a aprovação "com um clique".

Para um guia detalhado sobre como usar o AccountManager:

No entanto, no final, o AccountManager armazena apenas seu token como texto sem formatação. Portanto, sugiro criptografar seu segredo antes de armazená-lo no AccountManager. Você pode utilizar várias bibliotecas de criptografia como o AESCrypt ou AESCrypto

Outra opção é usar a biblioteca Conceal . É seguro o suficiente para o Facebook e muito mais fácil de usar do que o AccountManager. Aqui está um trecho de código para salvar um arquivo secreto usando o Conceal.

byte[] cipherText = crypto.encrypt(plainText);
byte[] plainText = crypto.decrypt(cipherText);
aldok
fonte
2
Boa dica que esconda. Parece muito fácil de usar. E para muitos casos de uso.
Lagos
Não foi possível encontrar o Ocultar através do link. Pode ser desativado
user1114 2/07
9

SharedPreferences não é um local seguro. Em um dispositivo enraizado, podemos facilmente ler e modificar xmls de SharedPrefereces de todos os aplicativos. Portanto, os tokens devem expirar relativamente frequentes. Mas, mesmo que um token expire a cada hora, os tokens mais recentes ainda podem ser roubados das SharedPreferences. O Android KeyStore deve ser usado para armazenamento e recuperação a longo prazo de chaves criptográficas que serão usadas para criptografar nossos tokens, a fim de armazená-los em, por exemplo, SharedPreferences ou um banco de dados. As chaves não são armazenadas no processo de um aplicativo e, portanto, são mais difíceis de serem comprometidas.

Tão mais relevante que um local é como eles próprios podem ser seguros, por exemplo, usando JWTs de vida curta assinados criptograficamente, criptografando-os usando o Android KeyStore e enviando-os com um protocolo seguro

apex39
fonte
9
Então, onde podemos armazená-los?
Milind Mevada
3
  1. No painel Projeto do Android Studio, selecione "Arquivos de Projeto" e crie um novo arquivo chamado "keystore.properties" no diretório raiz do seu projeto.

insira a descrição da imagem aqui

  1. Abra o arquivo "keystore.properties" e salve seu token e segredo de acesso no arquivo.

insira a descrição da imagem aqui

  1. Agora carregar a ler o token de acesso e segredo em seu aplicativo do módulo build.gradle arquivo. Em seguida, você precisa definir a variável BuildConfig para o seu token e segredo de acesso, para que você possa acessá-los diretamente do seu código. Seu build.gradle pode parecer com o seguinte:

    ... ... ... 
    
    android {
        compileSdkVersion 26
    
        // Load values from keystore.properties file
        def keystorePropertiesFile = rootProject.file("keystore.properties")
        def keystoreProperties = new Properties()
        keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
    
        defaultConfig {
            applicationId "com.yourdomain.appname"
            minSdkVersion 16
            targetSdkVersion 26
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    
            // Create BuildConfig variables
            buildConfigField "String", "ACCESS_TOKEN", keystoreProperties["ACCESS_TOKEN"]
            buildConfigField "String", "SECRET", keystoreProperties["SECRET"]
        }
    }
  2. Você pode usar seu token e segredo de acesso em seu código como este:

    String accessToken = BuildConfig.ACCESS_TOKEN;
    String secret = BuildConfig.SECRET;

Dessa forma, você não precisa armazenar o token e o segredo de acesso em texto sem formatação dentro do seu projeto. Portanto, mesmo que alguém descompile seu APK, eles nunca receberão seu token e segredo de acesso enquanto você os carrega de um arquivo externo.

Zahidur Rahman Faisal
fonte
1
Parece que não há diferença que a criação de um arquivo de propriedades seja codificada.
Dzshean
Quero escrever Token em tempo de execução. Meu token é sempre alterado quando abro meu aplicativo.
Rehan Sarwar
1
É uma maneira muito boa de armazenar alguns tokens, como tokens de acesso à API. se você deseja armazenar credenciais de usuário, o NDK é a melhor maneira.
Eric
6
Não é absolutamente assim que você deve armazenar informações confidenciais em seu aplicativo! Mesmo que o repositório não contenha os dados usando essa abordagem (os dados são injetados no processo de compilação), isso gera um arquivo BuildConfig que possui o token / segredo em texto sem formatação para que todos possam ver após uma simples descompilação.
precisa saber é o seguinte
-1

Bem, você pode proteger seu acesso ao token seguindo duas opções.

  1. Use salvar seu token de acesso no keystore do Android que não seria inverso.
  2. Use a função NDK com algum cálculo que salve seu token e NDK com código c ++ que é muito difícil de reverter
M.Noman
fonte