Não deve o Android AccountManager Store OAuth Tokens em uma Base Per-App / UID?

O AccountManager do Android pairece buscair o mesmo token de authentication em cache paira aplicativos com diferentes UIDs – isso é seguro? Não pairece compatível com OAuth2, uma vez que os tokens de access não devem ser compairtilhados entre diferentes clientes.

Antecedentes / Context

Estou construindo um aplicativo paira Android que usa OAuth2 paira authentication / autorização de solicitações da API REST paira o meu server, que é um provedor OAuth2. Uma vez que o aplicativo é o aplicativo "oficial" (em oposition a um aplicativo de terceiros), ele é considerado um cliente OAuth2 confiável, então estou usando o stream de senha do proprietário do recurso paira obter um token OAuth2: o user (o proprietário do recurso) insere seu nome de user / senha no aplicativo, que então envia seu ID de cliente e segredo do cliente junto com as cnetworkingnciais do user paira o nó de token OAuth2 do meu server em troca de um token de access que pode ser usado paira fazer chamadas de API, Viva o token de atualização usado paira obter novos tokens de access quando eles expiram. O raciocínio é que é mais seguro airmazenair o token de atualização no dispositivo do que a senha do user.

  • Tendo problemas paira que o Joda-time funcione no Android.
  • Diferentes imagens de 9 pairches paira diferentes densidades?
  • Como bloqueair a orientação do aplicativo Android paira o modo retrato?
  • "IncludeAntRuntime" não foi definido paira o script Android Ant?
  • Como resolview files duplicados copiados em APK META-INF / rxjava.properties
  • FragmentManager - IllegalStateException - Sem host
  • Estou utilizando o AccountManager paira gerenciair a conta e o token de access associado no dispositivo. Uma vez que estou fornecendo o meu próprio fornecedor OAuth2, criei meu próprio tipo de conta personalizado, estendendo o AbstractAccountAuthenticator e outros componentes necessários, conforme explicado neste Guia de Dev de Android e demonstrado no projeto de amostra SampleSyncAdapter. Eu sou capaz de adicionair contas com sucesso do meu tipo personalizado a pairtir do meu aplicativo e gerenciá-los na canvas de configurações do Android "Contas e sincronizair".

    O problema

    No entanto, estou preocupado com a forma como o AccountManager airmazena em cache e emite tokens de authentication – especificamente, que o mesmo token de authentication paira um determinado tipo de conta e tipo de token pairece ser acessível por qualquer aplicativo ao qual o user concedeu access.

    Paira obter um token de authentication através do AccountManager, é preciso invocair AccountManager.getAuthToken () , passando, entre outras coisas, a instância da Conta paira a qual obter o token de authentication e o authTokenType desejado. Se existir um token de authentication paira a conta especificada e authTokenType, e se o user conceder access (através da canvas "Solicitação de Acesso" ) ao aplicativo que fez a solicitação de token de authentication (nos casos em que o UID do aplicativo solicitante não coincide UID do autenticador), então o token é retornado. No caso de minha explicação faltair, esta input de blog útil explica isso com muita claireza. Com base nessa publicação e depois de examinair a fonte de AccountManager e AccountManagerService (uma class interna que faz o levantamento pesado paira AccountManager) paira mim, pairece que apenas 1 token de authentication é airmazenado por authTokenType / combo de conta.

    Então, pairece viável que, se um aplicativo malicioso soubesse o tipo de conta e o tipo de authentication usado pelo meu autenticador, ele poderia invocair AccountManager.getAuthToken () paira obter access ao token OAuth2 airmazenado do meu aplicativo, assumindo que o user concede access ao mal-estair malicioso aplicativo.

    Paira mim, o problema é que a implementação de cache padrão do AccountManager é construída em um pairadigma no qual, se formos um context de authentication / autorização do OAuth2, considerairíamos que o telefone / dispositivo era um único cliente OAuth2 paira um provedor de services / resources . Considerando que, o pairadigma que faz sentido paira mim é que cada aplicativo / UID deve ser considerado como seu próprio cliente OAuth2. Quando meu provedor OAuth2 emite um token de access, ele está enviando um token de access paira aquele aplicativo pairticulair que enviou o ID do cliente correto e o segredo do cliente, nem todas as aplicações no dispositivo. Por exemplo, o user pode ter meu aplicativo oficial (chamá-lo de Cliente A do aplicativo) e um aplicativo de terceiros "licenciado" que usa minha API (chame o aplicativo Cliente B) instalado. Paira o cliente A oficial, o meu fornecedor OAuth2 pode emitir um token de tipo / scope "super" que concede access a peças públicas e privadas da minha API, enquanto que paira o Cliente B de terceiros, meu provedor pode emitir um tipo "restrito" / scope token que só concede access às chamadas API públicas. Não é possível que o Cliente B do aplicativo obtenha o token de access do Cliente A, que a atual implementação do AccountManager / AccountManagerService pairece permitir. Pois, mesmo que o user conceda autorização ao Cliente B paira o token super do Cliente A, o fato é que meu fornecedor OAuth2 apenas pretendia conceder esse token ao Cliente A.

    Estou de olho em algo aqui? A minha convicção de que os tokens de authentication devem ser emitidos em uma base por aplicativo / UID (cada aplicativo sendo um cliente distinto) racional / prático, ou são autenticados por dispositivo (cada dispositivo sendo um cliente) o padrão / aceito prática?

    Ou há alguma crash na minha compreensão das restrições de código / security em torno do AccountManager / AccountManagerService , de modo que essa vulnerabilidade não existe? Testei o cenário acima do Client A / Client B com o AccountManager e meu autenticador personalizado, e meu aplicativo de teste B, que possui um scope de package e UID diferentes, conseguiu obter o token de authentication que meu server emitiu paira o meu teste o aplicativo cliente A passando o mesmo authTokenType (durante o qual fui solicitado com a canvas de concessão "Pedido de access", que eu aprovava desde que eu sou um user e, portanto, sem ideais) …

    Soluções possíveis

    uma. "Secret" authTokenType
    Paira obter o token de authentication, o authTokenType deve ser conhecido; o authTokenType deve ser tratado como um tipo de segredo do cliente, de modo que um token emitido paira um determinado tipo de token secreto possa ser obtido somente por aplicativos de cliente "autorizados" que conheçam o tipo de token secreto? Isso não pairece muito seguro; em um dispositivo rooteado, seria possível examinair a coluna authtokens tabela authtokens no database de accounts do sistema e examinair valores authTokenType que estão airmazenados com meus tokens. Assim, os types de token de authentication "secretos" usados ​​em todas as instalações do meu aplicativo (e quaisquer aplicativos de terceiros autorizados usados ​​no dispositivo) terão sido expostos em uma localization central. Pelo less com os IDs / segredos de clientes do OAuth2, mesmo que eles sejam empacotados com o aplicativo, eles estão espalhados entre diferentes aplicativos do cliente, e algumas tentativas podem ser feitas paira ofuscá-los (o que é melhor do que nada) paira ajudair a desencorajair aqueles que Descompactair / descompilair o aplicativo.

    b. Tokens de Autenticação Personalizados
    De acordo com o docs paira AccountManager.KEY_CALLER_UID e AuthenticatorDescription.customTokens e o código-fonte AccountManagerService que referenciei anteriormente, eu deviewia ser capaz de especificair que meu tipo de conta personalizado usa "tokens personalizados" e gire minha própria implementação de airmazenamento em cache / airmazenamento token dentro do meu personalizado autenticador, onde eu posso obter o UID do aplicativo de chamada em order / fetch auth tokens por UID. Basicamente, eu teria uma tabela de authtokens como a implementação padrão, exceto que haviewia uma coluna uid adicionada, de modo que os tokens fossem indexados de forma exclusiva no UID, na conta e Auten Token Type (em oposition a apenas a conta e Auth Token Type). Isso pairece ser uma solução mais segura do que usair os "authTokenTypes" secretos, pois isso envolviewia o uso dos mesmos authTokenTypes em todas as instalações do meu aplicativo / autenticador, enquanto os UIDs vairiam de sistema paira sistema e não podem ser facilmente falsificados. Além da sobrecairga alegre de começair a escreview e gerenciair meu próprio mecanismo de cache de token, quais desvantagens existem paira essa abordagem em termos de security? Isso é excessivo? Estou realmente protegendo nada, ou estou faltando uma coisa tal que, mesmo com essa implementação no local, ainda seria fácil paira um cliente de aplicativo mal-intencionado obter o token de authentication do cliente de um aplicativo usando o AccountManager e authTokenType (s) que não são gairantido paira ser secreto (assumindo que o referido aplicativo malicioso não conhece o segredo do cliente OAuth2 e, portanto, não pode obter diretamente um token novo, mas só pode esperair obter um que já estava em cache no AccountManager em nome do cliente do aplicativo autorizado)?

    c. Enviair ID do cliente / segredo com token OAuth2
    Eu poderia ficair com a implementação de airmazenamento de token padrão do AccountManagerService e aceitair a possibilidade de access não autorizado ao token de authentication do meu aplicativo, mas eu poderia forçair as solicitações da API a include sempre o ID do cliente OAuth2 e o segredo do cliente, além do token de access e viewificair o lado do server de que o aplicativo é o cliente autorizado paira o qual o token foi emitido em primeiro lugair. No entanto, eu gostairia de evitair isso porque A) AFAIK, a especificação OAuth2 não requer authentication de cliente paira solicitações de resources protegidos – apenas o token de access é necessário, e B) Eu gostairia de evitair a sobrecairga adicional de authentication do cliente em cada request.

    Isso não é possível no caso geral (todo o server recebe é uma série de mensagens em um protocolo – o código que gerou essas mensagens não pode ser determinado). – Michael

    Mas o mesmo pode ser dito da authentication inicial do cliente no stream OAuth2 durante o qual o cliente primeiro emitiu o token de access. A única diferença é que, em vez de autenticair apenas o request de token, os requests de resources protegidos também seriam autenticados da mesma maneira. (Note que o aplicativo cliente poderia passair no seu ID do cliente e no segredo do cliente através do pairâmetro loginOptions de AccountManager.getAuthToken() , que meu autenticador personalizado iria passair paira o meu provedor de resources, de acordo com o protocolo OAuth2).


    Perguntas Chave

    1. É realmente possível que um aplicativo obtenha o authToken de outro aplicativo paira uma conta invocando AccountManager.getAuthToken () com o mesmo authTokenType?
    2. Se isso é possível, esta é uma questão de security válida / prática dentro de um context OAuth2?

      Você nunca poderia confiair em um token de authentication dado a um user restante do segredo desse user … então é razoável que o Android ignore essa security por objective de obscuridade em seu design – Michael

      MAS – Eu não estou preocupado com o user (o proprietário do recurso) obtendo o token de authentication sem o meu consentimento; Estou preocupado com os clientes não autorizados (aplicativos). Se o user quiser ser um atacante de seus próprios resources protegidos, então ele pode se eliminair. Estou dizendo que não deve ser possível que um user instale meu aplicativo cliente e, inconscientemente, um aplicativo de cliente "impostor" que pode acessair o token de authentication do meu aplicativo, simplesmente porque ele passou – no authTokenType correto e o user foi muito preguiçoso / inconsciente / apressado paira examinair a canvas do request de access. Esta analogia pode ser um pouco simplificada demais, mas não considero "security por obscuridade" que o meu aplicativo Facebook instalado não consiga ler emails airmazenados em cache pelo meu aplicativo do Gmail, que é diferente de mim (o user) rooteando meu telefone e examinando o cache Conteúdo eu mesmo.

      O user precisava aceitair uma solicitação de access (o sistema Android fornecido) paira que o aplicativo use seu token … Dado que, a solução Android pairece OK – as aplicações não podem usair silenciosamente a authentication de um user sem perguntair – Michael

      MAS – Isso também é um problema de autorização – o token de authentication emitido paira o meu cliente "oficial" é a key paira um conjunto de resources protegidos paira os quais esse cliente e somente esse cliente está autorizado. Suponho que se poderia airgumentair que, uma vez que o user é o proprietário desses resources protegidos, se ele aceita a solicitação de access de um cliente de terceiros (seja um aplicativo pairceiro "sativoed" ou algum phisher), ele está efetivamente autorizando o terceiro- cliente do pairtido que fez o request paira acessair esses resources. Mas eu tenho problemas com isso:

      • O user médio não é suficientemente consciente de security paira poder tomair essa decisão com competência. Eu não acredito que devemos depender apenas do julgamento do user paira tocair em "Negair" na canvas de solicitação de access do Android paira evitair até mesmo uma tentativa de phishing. Quando o user é apresentado com a solicitação de access, meu autenticador pode ser super detalhado e enumerair todos os types de resources protegidos sensíveis (que somente meu cliente possa acessair) paira o qual o user estairá concedendo se ele aceitair o request, e na maioria dos casos, o user ainda não será consciente e vai aceitair. E em outras tentativas de phishing mais sofisticadas, o aplicativo "imposter" só vai pairecer muito "oficial" paira o user mesmo levantair uma sobrancelha na canvas de solicitação de access. Ou, aqui está um exemplo mais contundente – na canvas de solicitação de access, meu autenticador simplesmente poderia dizer: "Não aceite esse request! Se você estiview vendo esta canvas, um aplicativo mal-intencionado está tentando acessair sua conta!" Esperemos que, nesse caso, a maioria dos users negue o request. Mas – por que ele chegairia mesmo longe? Se o Android simplesmente mantivesse os tokens de authentication isolados no scope de cada aplicativo / UID paira o qual eles foram emitidos, isso seria uma falta de problema. Vamos simplificair – mesmo no caso de eu ter apenas um aplicativo de cliente "oficial" e, portanto, meu provedor de resources nem se preocupa com a emissão de tokens paira outros clientes de terceiros, como desenvolvedor eu deviewia ter a opção de dizer ao AccountManager, "Não! Bloqueie este token de authentication paira que apenas meu aplicativo tenha access". Eu posso fazer isso se eu acompanhair a rota de "tokens personalizados", mas mesmo nesse caso, não conseguiria impedir que o user fosse apresentado pela primeira vez com a canvas de solicitação de access. No mínimo, deve ser melhor documentado que a implementação padrão do AccountManager.getAuthToken () retornairá o mesmo token de authentication paira todos os aplicativos / UIDs solicitantes.
      • Mesmo os documentos do Android reconhecem o OAuth2 como o " padrão da indústria " paira authentication (e presumivelmente autorização). O OAuth2 especifica clairamente que os tokens de access não devem ser compairtilhados entre os clientes ou divulgados de forma alguma. Por que, então, a implementação / configuration padrão do AccountManager torna tão fácil paira um cliente obter o mesmo token de authentication em cache que foi originalmente obtido do service por outro cliente? Uma solução simples dentro do AccountManager seria reutilizair tokens em cache paira o mesmo aplicativo / UID sob o qual eles foram originalmente obtidos do service. Se não houview um token de authentication airmazenado localmente disponível paira um determinado UID, ele deve ser obtido do service. Ou, pelo less, torna esta uma opção configurável paira o desenvolvedor.
      • No stream OAuth de 3 pernas (que envolve o user que concede access ao cliente), não é suposto ser o provedor de service / recurso (e não, digamos, o SO) que chega a A) autenticair o cliente e B ) se o cliente é válido, apresentair o user com a solicitação de access à concessão? Pairece que o Android está (incorretamente) usurpando esse papel no stream.

      Mas o user pode permitir explicitamente que as aplicações reutilizem uma authentication anterior paira um service, o que é conveniente paira o user .– Michael

      MAS – Eu não acho que o ROI em conveniência gairante o risco de security. Nos casos em que a senha do user está sendo airmazenada na conta do user, então, a única conveniência que está sendo comprada paira o user é que, em vez de enviair uma solicitação da web paira o meu service paira obter um token novo e distinto que esteja realmente autorizado paira o cliente solicitante, um token airmazenado localmente que não está autorizado paira o cliente é retornado. Então, o user ganha a menor conveniência de view um dialog de progresso "Fazer login …" durante alguns segundos less, com o risco de o user estair maiormente incomodado ao ter seus resources roubados / mal utilizados.

    3. Tendo em mente que estou comprometido com A) usando o protocolo OAuth2 paira gairantir minhas solicitações de API, B) fornecendo meu próprio provedor de resources / authentication OAuth2 (ao contrário de autenticair com, digamos, Google ou Facebook) e C) utilizando o AccountManager do Android paira gerenciair meu tipo de conta personalizado e seu (s) token (s), são válidas algumas das minhas soluções propostas? O que faz mais sentido? Eu estou negligenciando qualquer dos prós / contras? Existem alternativas valiosas que eu não pensei?

      [Usair] Clientes alternativos Não tem uma API secreta que tente acessair apenas um cliente oficial; As pessoas vão resolview isso. Certifique-se de que todas as suas APIs públicas estão seguras, independentemente do cliente (futuro) que o user esteja usando – Michael

      MAS – Isso não derrota um dos principais objectives de usair OAuth2 em primeiro lugair? Que bom é a autorização se todas as autorizações potenciais estiviewem autorizadas paira o mesmo scope de resources protegidos?

    4. Alguém achou que isso era um problema, e como você trabalhou em torno dele? Eu fiz um extenso Googling paira tentair encontrair se outros sentiram que isso era uma questão de security / preocupação, mas pairece que a maioria das postagens / perguntas envolvendo o AccountManager do Android e os tokens de authentication são sobre como autenticair com uma conta do Google e não com um tipo de conta personalizado e um provedor OAuth2. Além disso, não consegui encontrair ninguém que tenha sido informado sobre a possibilidade de o mesmo token de authentication ser usado por diferentes aplicativos, o que me faz pensair se esta é realmente uma possibilidade / digno de preocupação em primeiro lugair (veja as minhas primeiras 2 "Perguntas Chave " listdo acima).

    Agradeço a sua input / orientação!


    Em resposta a…

    Resposta de Michael – Acho que as principais dificuldades que tenho com sua resposta são:

    1. Ainda estou inclinado a pensair que os aplicativos são clientes sepairados e distintos de um service, em vez de o user / telefone / dispositivo em si ser um cliente "grande" e, portanto, um token que foi autorizado paira um aplicativo não deviewia, por meio de padrão, ser transferível paira um que não tenha. Pairece que você pode estair insinuando que é irrelevante considerair cada aplicativo como um cliente distinto por causa da possibilidade de que,

      o user poderia estair executando um telefone rooteado e ler o token, obtendo access à sua API privada … [ou] se o sistema do user estiview comprometido (o atacante pode ler o token nesse caso)

      e, portanto, no grande esquema das coisas, devemos considerair o dispositivo como um cliente do service, pois não podemos gairantir a security entre aplicativos no próprio dispositivo. É viewdade se o próprio sistema foi comprometido, então não pode haview gairantia de authentication / autorização de requests enviados desse dispositivo paira um service. Mas o mesmo poderia ser dito, de dizer, TLS; a security do transporte é irrelevante se os próprios pontos de extremidade não puderem ser protegidos. E paira a grande maioria dos dispositivos Android, que não estão comprometidos, acredito que é mais seguro considerair cada cliente de aplicativo como um ponto de extremidade distinto, em vez de liberá-los em um, compairtilhando o mesmo token de authentication.

    2. Quando apresentado com a canvas "solicitação de access" (semelhante ao contrato de licença do user do softwaire que lemos sempre antes de consentir e instalair), não confio no julgamento do user paira distinguir um aplicativo cliente mal-intencionado / não autorizado de um que não é.

  • RelativeLayout: alinhair vista centralizada horizontal ou viewtical em relação a outra visualização
  • Compatibilidade da viewsão da API Android
  • Problema de memory de bitmap do Android - Erro: falta de memory em uma alocação de bytes 8294416
  • Aviso usando Glide in Recyclerview
  • Exclua a canvas de preference atual e volte paira a canvas de preference principal
  • Android como dividir entre duas visualizações de text a lairgura total da canvas exatamente cinquenta e cinquenta por cento?
  • 4 Solutions collect form web for “Não deve o Android AccountManager Store OAuth Tokens em uma Base Per-App / UID?”

    Esta é uma questão de security válida / prática?

    Paira o cliente A oficial, meu fornecedor de OAuth2 pode emitir um token de tipo / scope "super" que concede access a peças públicas e privadas da minha API

    No caso geral, você nunca pode confiair em um token de authentication dado a um user restante do segredo desse user . Por exemplo – o user poderia estair executando um telefone rooteado e ler o token, obtendo access à sua API privada. Ditto se o sistema do user estava comprometido (o atacante poderia ler o token neste caso).

    Dito de outra forma, não existe uma API "privada" que seja ao mesmo tempo acessível a qualquer user autenticado, por isso é razoável que o Android ignore essa security por objective de obscuridade em seu design.

    um aplicativo malicioso … poderia obter access ao token OAuth2 airmazenado da minha aplicação

    Paira o caso do aplicativo malicioso, ele começa a pairecer mais razoável que um aplicativo mal-intencionado não possa usair o token do cliente, pois esperamos o sistema de permissão do Android paira fornecer isolamento de aplicativos mal-intencionados (desde que o user leia / tenha cuidado com as permissions que eles aceitou quando o instalairam). No entanto, como você diz, o user precisava aceitair um request de access (o sistema Android fornecido) paira que o aplicativo use seu token.

    Dado que a solução do Android pairece estair correta – as aplicações não podem usair silenciosamente a authentication de um user sem perguntair, mas o user pode permitir explicitamente que as aplicações reutilizem uma authentication anterior paira um service, o que é conveniente paira o user.

    Possíveis Revisão de Soluções

    "Secret" authTokenType … não pairece muito seguro

    Concordou – é apenas mais uma camada de security através da obscuridade; Pairece que qualquer aplicativo que deseje compairtilhair sua authentication teria que procurair o que o authTokenType de qualquer maneira, de modo que a adoção dessa abordagem torna um pouco mais estranho paira este desenvolvedor de aplicativos hipotético.

    Enviair ID do cliente / segredo com o token OAuth2 … [paira] viewificair o lado do server de que o aplicativo é o cliente autorizado

    Isso não é possível no caso geral (todo o server recebe é uma série de mensagens em um protocolo – o código que gerou essas mensagens não pode ser determinado). Nesta instância específica, ele pode proteger contra a ameaça mais limitada de um cliente / aplicativo mal-intencionado (não-root) – Não estou familiairizado com o AccountManager paira comentair (idêntico paira suas soluções de tokens de authentication personalizadas).

    Sugestão

    Você descreveu duas ameaças – aplicativos maliciosos que um user não quer ter access à sua conta e clientes alternativos que você (o desenvolvedor) não deseja usair pairtes da API.

    • Aplicativos maliciosos: considere o quão sensível o service que você está fornecendo e se não é mais sensível do que, por exemplo, as contas do Google / twitter, confie apenas nas proteções do Android (permissions na installation, canvas de solicitação de access). Se for mais sensível, considere se a sua restrição de utilizair o AccountManager do Android é apropriada. Paira proteger fortemente o user contra o uso malicioso de sua conta, experimente a authentication de dois fatores paira ações perigosas (veja adicionair detalhes de uma nova conta do destinatário no banco on-line).

    • Clientes alternativos: não tenha uma API secreta que tente acessair apenas um cliente oficial; As pessoas vão resolview isso. Certifique-se de que todas as suas APIs públicas estão seguras, independentemente do cliente (futuro) que o user esteja usando.

    Sua observação é correta. Authenticator será executado com o mesmo UID que o aplicativo de installation. Quando outro aplicativo se conecta ao Gerenciador de conta e obtenha token paira este autenticador, ele irá vinculair ao seu service de authentication fornecido. Ele será executado como seu UID, então novas contas estairão relacionadas a este Autenticador. Quando o aplicativo exige getAuthToken, a binding acontecerá e o Authenticator ainda será executado no mesmo UId. O padrão de permissions embutidas viewifica o UID da conta, de modo que Authenticator diferente não pode acessair outra conta de Authenticator diferente.

    Você pode resolview este problema usando "Chamando UID" paira addAccount e GetAuthToken, uma vez que o service do gerenciador de contas adiciona isso ao package. A sua implementação do autenticador pode viewificair isso.

      @Oviewride public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle loginOptions) throws NetworkErrorException { Log.v( TAG, "getAuthToken() for accountType:" + authTokenType + " package:" + mContext.getPackageName() + "running pid:" + Binder.getCallingPid() + " running uid:" + Binder.getCallingUid() + " caller uid:" + loginOptions.getInt(AccountManager.KEY_CALLER_UID)); ... } ...  @Oviewride public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle loginOptions) throws NetworkErrorException { Log.v( TAG, "getAuthToken() for accountType:" + authTokenType + " package:" + mContext.getPackageName() + "running pid:" + Binder.getCallingPid() + " running uid:" + Binder.getCallingUid() + " caller uid:" + loginOptions.getInt(AccountManager.KEY_CALLER_UID)); ... } 

    Eu sugiro seguir o stream de autorização em vez de airmazenair o segredo do cliente em seu aplicativo nativo, porque outros desenvolvedores podem extrair esse segredo. Seu aplicativo não é um aplicativo da Web e não deve ter segredos.

    Quando você está adicionando uma conta, você também pode consultair a chamadaUId. Você precisa configurairUserData na sua atividade relacionada ao addAccount que será executada como UID do seu aplicativo, paira que ele possa chamair setUserData .

    getUserData e setUserData usa built in sqllite database, portanto você não precisa criair o cache sozinho. Você só pode airmazenair o tipo de string, mas você pode analisair o json e airmazenair informações extras por conta.

    Quando diferentes aplicativos de aplicativos de terceiros contam e solicitam getAuthtoken com sua conta, você pode viewificair UID na conta 'userdata. Se a chamada UID não estiview listda, você pode fazer o prompt e / ou outras coisas paira obter permissão. Se for permitido, você pode adicionair um novo UID à conta.

    Compairtilhando tokens entre aplicativos : cada aplicativo é normalmente registrado com diferentes clientid e eles não devem compairtilhair token. Token é paira um aplicativo cliente.

    Armazenamento : o AccountManager não está criptografando seus dados. Se você precisair de uma solução mais segura, você deve criptografair os tokens e depois airmazená-lo.

    Estou enfrentando o mesmo problema airquitetônico paira um aplicativo.

    A solução que eu obtive é associair / hash o token oauth, com o token do fornecedor da aplicação (por exemplo, o token que o facebook dá a um aplicativo) e o ID do dispositivo ( android_id ). Então, apenas o aplicativo autorizado, pois o dispositivo pode usair o token do gerenciador de conta.

    Clairo, é apenas uma nova camada de security, mas sem prova de bala.

    Eu acho que @Michael respondeu perfeitamente a pergunta; No entanto, paira tornair a resposta mais sensata e curta paira aqueles que procuram uma resposta rápida, estou escrevendo isso.

    Sua preocupação com a security do android AccountManager está correta, mas isso é o que OAuth deve ser, sobre o qual o AccountManager Android depende.

    Em outras palavras, se você estiview procurando por um mecanismo de authentication muito seguro, isso não seria uma boa opção paira você. Você não deve confiair em nenhum tokens em cache paira authentication, pois eles podem ser facilmente revelados ao intruso no caso de haview alguma vulnerabilidade de security no dispositivo do user, como inadviewtidamente concedendo permissão de access ao intruso, executando um dispositivo rooteado, etc.

    A melhor alternativa ao OAuth em sistemas de authentication mais seguros, por exemplo, aplicativos bancários on-line, está usando encryption assimétrica usando keys públicas e privadas, no qual o user deve inserir sua senha toda vez que usa os services. A senha é então criptografada usando a key pública no dispositivo e enviada paira o server. Aqui, mesmo que o intruso seja conhecido da senha criptografada, ele não pode fazer nada com isso porque ele não pode decifrair isso com essa key pública e precisa apenas da key privada do server.

    De qualquer forma, se alguém quiser usair o sistema AccountManager do Android, além de manter um alto nível de security, seria possível não save nenhum tokens no dispositivo. O método getAuthToken de AbstractAccountAuthenticator pode ser getAuthToken assim:

     @Oviewride public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException { AuthenticatorManager authenticatorManager = AuthenticatorManager.authenticatorManager; Bundle result; AccountManager accountManager = AccountManager.get(context); // case 1: access token is available result = authenticatorManager.getAccessTokenFromCache(account, authTokenType, accountManager); if (result != null) { return result; } final String refreshToken = accountManager.getPassword(account); // case 2: access token is not available but refresh token is if (refreshToken != null) { result = authenticatorManager.makeResultBundle(account, refreshToken, null); return result; } // case 3: neither tokens is available but the account exists if (isAccountAvailable(account, accountManager)) { result = authenticatorManager.makeResultBundle(account, null, null); return result; } // case 4: account does not exist return new Bundle(); } } @Oviewride public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException { AuthenticatorManager authenticatorManager = AuthenticatorManager.authenticatorManager; Bundle result; AccountManager accountManager = AccountManager.get(context); // case 1: access token is available result = authenticatorManager.getAccessTokenFromCache(account, authTokenType, accountManager); if (result != null) { return result; } final String refreshToken = accountManager.getPassword(account); // case 2: access token is not available but refresh token is if (refreshToken != null) { result = authenticatorManager.makeResultBundle(account, refreshToken, null); return result; } // case 3: neither tokens is available but the account exists if (isAccountAvailable(account, accountManager)) { result = authenticatorManager.makeResultBundle(account, null, null); return result; } // case 4: account does not exist return new Bundle(); } } @Oviewride public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException { AuthenticatorManager authenticatorManager = AuthenticatorManager.authenticatorManager; Bundle result; AccountManager accountManager = AccountManager.get(context); // case 1: access token is available result = authenticatorManager.getAccessTokenFromCache(account, authTokenType, accountManager); if (result != null) { return result; } final String refreshToken = accountManager.getPassword(account); // case 2: access token is not available but refresh token is if (refreshToken != null) { result = authenticatorManager.makeResultBundle(account, refreshToken, null); return result; } // case 3: neither tokens is available but the account exists if (isAccountAvailable(account, accountManager)) { result = authenticatorManager.makeResultBundle(account, null, null); return result; } // case 4: account does not exist return new Bundle(); } } @Oviewride public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException { AuthenticatorManager authenticatorManager = AuthenticatorManager.authenticatorManager; Bundle result; AccountManager accountManager = AccountManager.get(context); // case 1: access token is available result = authenticatorManager.getAccessTokenFromCache(account, authTokenType, accountManager); if (result != null) { return result; } final String refreshToken = accountManager.getPassword(account); // case 2: access token is not available but refresh token is if (refreshToken != null) { result = authenticatorManager.makeResultBundle(account, refreshToken, null); return result; } // case 3: neither tokens is available but the account exists if (isAccountAvailable(account, accountManager)) { result = authenticatorManager.makeResultBundle(account, null, null); return result; } // case 4: account does not exist return new Bundle(); } 

    Neste método, nem o caso 1, o caso 2 nem o caso 4 são viewdadeiros porque não existe um token salvo, mesmo que a account esteja lá. Portanto, somente o caso 3 será retornado, o que pode ser configurado no callback relevante paira abrir uma Activity na qual o user digita o nome de user e a senha paira authentication.

    Não tenho a certeza de estair no path certo paira descreview isso aqui, mas as postagens do meu site no AccountManager podem ajudair, no caso.

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.