Segredos OAuth em aplicativos móveis

137

Ao usar o protocolo OAuth, você precisa de uma sequência secreta obtida do serviço ao qual deseja delegar. Se você estiver fazendo isso em um aplicativo Web, poderá simplesmente armazenar o segredo em sua base de dados ou no sistema de arquivos, mas qual é a melhor maneira de lidar com isso em um aplicativo móvel (ou um aplicativo de desktop)?

O armazenamento da string no aplicativo obviamente não é bom, pois alguém pode encontrá-la e abusá-la facilmente.

Outra abordagem seria armazená-lo em seu servidor e fazer com que o aplicativo o buscasse a cada corrida, nunca armazenando-o no telefone. Isso é quase tão ruim, porque você precisa incluir o URL no aplicativo.

A única solução viável que eu posso encontrar é primeiro obter o token de acesso normalmente (de preferência usando uma visualização da Web dentro do aplicativo) e, em seguida, encaminhar toda a comunicação adicional através do nosso servidor, o que acrescentaria o segredo aos dados solicitados e comunicaria com o provedor. Por outro lado, sou um noob de segurança, então eu realmente gostaria de ouvir as opiniões de algumas pessoas com conhecimento sobre isso. Não me parece que a maioria dos aplicativos atenda a esses limites para garantir a segurança (por exemplo, o Facebook Connect parece assumir que você coloca o segredo em uma sequência correta no seu aplicativo).

Outra coisa: não acredito que o segredo esteja envolvido na solicitação inicial do token de acesso, para que isso possa ser feito sem envolver nosso próprio servidor. Estou correcto?

Felixyz
fonte
Desculpe se eu não entendi o óbvio, mas qual é o problema em armazenar os códigos no banco de dados do aplicativo? Como esses tokens são gerados e armazenados depois que o usuário autenticou sua conta, é seguro presumir que o usuário deseje que o dispositivo móvel armazene o acesso para ter acesso.
poke
Mesmo depois que o usuário o autorizou a acessar a conta (no Twitter, por exemplo), você precisa usar um segredo que obteve do serviço que está tentando acessar. Esse segredo é usado em toda comunicação com o servidor, junto com a chave de autenticação e algumas outras chaves. Portanto, sim, você pode armazenar a chave de acesso, mas o segredo não deve ser armazenado, pois pode ser usado com qualquer chave de autenticação para abusar do serviço. Mais uma vez, eu ficaria feliz em ser corrigido por pessoas que sabem mais sobre isso.
19119 Felixyz
1
OAuth oferece um método de autenticação que protege os dados de login do usuário original. Para tornar isso possível, é gerada uma nova combinação de logon exclusiva que funciona apenas em conjunto com a combinação de teclas do aplicativo exclusivo . O grande benefício de armazenar os dados de login do usuário é que eles são completamente seguros após a primeira autorização e, em qualquer caso de violação, o usuário pode simplesmente revogar o acesso à autorização. E, é claro, não salvar o segredo não faria sentido, pois o usuário precisaria se autenticar novamente (e não é isso que o usuário deseja ao fornecer acesso ao aplicativo).
19409 poke
@poke A chave de autenticação obtida quando o usuário aprova seu aplicativo com o provedor deve ser salva, mas o token secreto que você recebeu do provedor antes de liberá-lo não deve (no caso de um aplicativo para computador ou celular; se for um aplicativo da Web, obviamente você pode armazenar a chave no servidor, conforme indicado na pergunta).
Felixyz
4
De acordo com meu entendimento do oAuth-- No caso de um aplicativo de desktop, é muito fácil detectar / monitorar o tráfego HTTP / HTTPS com ferramentas como ieinspector.com/httpanalyzer/index.html Portanto, seu segredo de token e token pode ser encontrado com muita facilidade. facilmente. Portanto, a única proteção é o seu segredo do consumidor. Agora, se sua loja é o segredo dentro do aplicativo e alguém é capaz de encontrá-lo, torna-se brincadeira de criança personificar qualquer outro aplicativo como seu aplicativo. Corrija-me se eu estiver errada.
Varun

Respostas:

38

Sim, esse é um problema com o design do OAuth que estamos enfrentando. Optamos por proxy de todas as chamadas através do nosso próprio servidor. OAuth não foi totalmente liberado em relação aos aplicativos de desktop. Não há uma solução perfeita para o problema que encontrei sem alterar o OAuth.

Se você pensar sobre isso e perguntar por que temos segredos, é principalmente para provisionar e desativar aplicativos. Se nosso segredo for comprometido, o provedor poderá realmente revogar todo o aplicativo. Como temos que incorporar nosso segredo no aplicativo de desktop, estamos meio que ferrados.

A solução é ter um segredo diferente para cada aplicativo de desktop. OAuth não facilita esse conceito. Uma maneira é fazer com que o usuário crie um segredo por conta própria e insira a chave por conta própria no seu aplicativo de desktop (alguns aplicativos do Facebook fizeram algo semelhante por um longo tempo, fazendo com que o usuário crie um facebook para configurar seus testes personalizados e porcaria). Não é uma ótima experiência para o usuário.

Estou trabalhando na proposta de um sistema de delegação para o OAuth. O conceito é que, usando nossa própria chave secreta que obtemos de nosso provedor, podemos emitir nosso próprio segredo delegado para nossos próprios clientes de desktop (um para cada aplicativo de desktop basicamente) e, durante o processo de autenticação, enviamos essa chave para o nível superior fornecedor que nos chama e volta a validar conosco. Dessa forma, podemos revogar os próprios segredos que divulgamos para cada cliente de desktop. (Emprestando muito de como isso funciona a partir do SSL). Todo esse sistema seria o prefeito de serviços da Web com valor agregado e que repassam chamadas para um serviço da Web de terceiros.

O processo também pode ser realizado sem retornos de chamada de verificação de delegação se o provedor de nível superior fornecer uma API para gerar e revogar novos segredos delegados. O Facebook está fazendo algo semelhante, permitindo que os aplicativos do Facebook permitam aos usuários criar sub-aplicativos.

Há algumas discussões sobre o problema online:

http://blog.atebits.com/2009/02/fixing-oauth/ http://groups.google.com/group/twitter-development-talk/browse_thread/thread/629b03475a3d78a1/de1071bf4b820c14#de1071bf4b820c14

A solução do Twitter e do Yammer é uma solução de pinos de autenticação: https://dev.twitter.com/oauth/pin-based https://www.yammer.com/api_oauth_security_addendum.html

Zac Bowling
fonte
Isso é muito interessante, embora confirme o que eu temia, que o OAuth não seja tão bom para aplicativos de desktop / dispositivos móveis. Obviamente, um invasor precisaria primeiro descobrir o segredo e, em seguida, também farejar as credenciais de alguém, para que fosse necessária alguma determinação. A solução de pinos é boa para desktops, mas é pesada para imo móvel.
Felixyz
Como seu esquema proposto ajudaria a agregar valor aos serviços da Web, já que esse problema não se aplica a eles? Além disso, não vejo como isso funcionaria com o provedor gerando novos segredos, já que você precisaria de um "segredo principal" para solicitar esses novos segredos; portanto, você precisaria de pelo menos uma chamada para seu próprio servidor (que contém o segredo principal). Mas isso é melhor do que rotear todo o tráfego através do seu próprio servidor. Esclarecimento muito bem-vindo! E atualize aqui à medida que sua proposta avança!
Felixyz 20/12/2009
5
Apenas curioso: como você determina que a coisa que está chamando o seu servidor proxy é legítima?
Davidtbernal
1
Em resposta a notJim: o principal risco ao permitir que o segredo do consumidor seja revelado é que aplicativos maliciosos (ou tolos) podem ser desenvolvidos usando-o, manchando sua reputação e aumentando o risco de o aplicativo legítimo ser desativado por abuso / mau uso da API. Ao fazer o proxy de todas as chamadas que exigem seu segredo por meio de um aplicativo da Web que você controla, você volta a uma posição em que pode observar padrões de abuso e revogar o acesso ao usuário ou nível de token de acesso antes que a API que você está consumindo decida fechar todo o seu serviço.
quasistoic
Concordo com o quasistoic aqui, você precisará usar um navegador habilitado para SSL para lidar com a chamada oauth. Isso é bom por alguns motivos, incluindo o gerenciamento fácil de quaisquer atualizações de segurança no futuro, e nada no aplicativo real precisará ser atualizado com o tempo. Zac aponta o Twitter propondo uma solução de PIN, que também pensei, porque você não pode confiar no aplicativo para obter o código com segurança. Sugiro o uso de um 'Nonce' com uma criptografia moderna, juntamente com o PIN e o segredo para proxy das solicitações por meio do servidor da web.
Mark
18

Com o OAUth 2.0, você pode armazenar o segredo no servidor. Use o servidor para adquirir um token de acesso que você move para o aplicativo e pode fazer chamadas diretamente do aplicativo para o recurso.

Com o OAuth 1.0 (Twitter), o segredo é necessário para fazer chamadas de API. Proxy de chamadas através do servidor é a única maneira de garantir que o segredo não seja comprometido.

Ambos exigem algum mecanismo que o componente do servidor saiba que é o seu cliente que está chamando. Isso costuma ser feito na instalação e no uso de um mecanismo específico da plataforma para obter um ID de aplicativo de algum tipo na chamada para o servidor.

Sou o editor da especificação do OAuth 2.0

Dick Hardt
fonte
2
Você pode elaborar sobre o "mecanismo específico da plataforma para obter algum tipo de ID de aplicativo"? Como é o componente do servidor para verificar a identidade do cliente? Eu acho que isso pode ser feito com o provisionamento do cliente. Por exemplo, implante um certificado SSL novo e exclusivo para cada cliente. É isso que você quer dizer? Se for mais complexo que isso, talvez você possa se referir a um artigo mais aprofundado?
Cheeso 16/09
2
Lembro-me de algumas pessoas de segurança falando sobre como isso poderia ser feito. Há uma chamada para o sistema operacional que retorna um token assinado que você pode enviar para o servidor e verificar. Desculpe, não tenho os detalhes. É um erro que poderia usar alguns bons exemplos.
Dick Hardt
2
@DickHardt, mas neste cenário, como você garante que o aplicativo móvel seja realmente seu aplicativo e não fraudulento?
Rafael Membrives
11

Uma solução poderia ser codificar o segredo do OAuth no código, mas não como uma sequência simples. Oculte-o de alguma forma - divida-o em segmentos, altere os caracteres por um deslocamento, gire-o - faça uma ou todas essas coisas. Um cracker pode analisar seu código de bytes e encontrar cadeias, mas pode ser difícil descobrir o código de ofuscação.

Não é uma solução infalível, mas barata.

Dependendo do valor da exploração, alguns crackers geniais podem se esforçar para encontrar seu código secreto. Você precisa pesar os fatores - custo da solução do servidor mencionada anteriormente, incentivo para que os crackers gastem mais esforços na busca de seu código secreto e a complexidade da ofuscação que você pode implementar.

Jayesh
fonte
1
Sim, acho que isso é razoável. Seria preciso muita determinação para alguém primeiro extrair o segredo do consumidor e depois arrebatar as credenciais das pessoas para fazer alguma coisa má. Para aplicativos de alto perfil, não tenho certeza se isso seria suficiente, mas para um aplicativo comum, acho que você está certo em equilibrar o tempo de implementação com uma ameaça de segurança bem menor.
Felixyz
7
Basta que um usuário faça o esforço e publique ou compartilhe seu segredo. Depois que seu segredo é revelado, o risco de seu serviço ser encerrado completamente por disparos de abuso e fica completamente fora de controle.
quasistoic
8
Ofuscação não é segurança. Isso é pior do que nenhuma segurança, porque fornece ao desenvolvedor uma falsa sensação de segurança. pt.wikipedia.org/wiki/Security_through_obscurity
Paul Legato
8
"Ocultação não é segurança. Isso é pior do que não segurança, porque dá ao desenvolvedor uma falsa sensação de segurança". Absurdo. Ninguém está dizendo que a ofuscação contribui para uma boa segurança. Mas se eu vou distribuir um segredo do OAuth com meu apk, é certamente melhor ofuscar do que não. Ocultação é o que o Google também recomenda ao armazenar chaves / segredos no aplicativo. Se nada mais, essas medidas mantêm os hackers casuais afastados, o que é melhor que nada. Declarações gerais como a sua igualam segurança imperfeita sem segurança. Isso simplesmente não é verdade. Imperfeito é apenas imperfeito.
Fomeghost 27/05
1
A ofuscação NÃO ajuda, porque, não importa quantas mudanças ou codificações você faça, você ainda constrói a chave juntas e a usa para criar sua solicitação de API. É bastante simples conectar APIs dinamicamente nos lugares certos para despejar a solicitação que você está enviando antes mesmo da criptografia HTTPS. Portanto, não incorpore chaves secretas no seu aplicativo, a menos que não haja realmente nenhuma alternativa possível.
C0deH4cker
6

Não guarde o segredo dentro do aplicativo.

Você precisa ter um servidor que possa ser acessado pelo aplicativo por https (obviamente) e armazenar o segredo nele.

Quando alguém quiser fazer login através do seu aplicativo móvel / desktop, seu aplicativo simplesmente encaminhará a solicitação ao servidor que anexará o segredo e o enviará ao provedor de serviços. Seu servidor pode dizer ao seu aplicativo se foi bem-sucedido ou não.

Então, se você precisar obter informações confidenciais do serviço (facebook, google, twitter, etc.), o aplicativo solicitará ao seu servidor e o servidor o fornecerá somente se estiver conectado corretamente.

Não há realmente nenhuma opção, exceto armazená-lo em um servidor. Nada no lado do cliente é seguro.

Nota

Dito isto, isso só o protegerá contra clientes mal-intencionados, mas não contra clientes mal-intencionados e nem contra outros clientes mal-intencionados (phising) ...

OAuth é um protocolo muito melhor no navegador do que no computador / dispositivo móvel.

Gudradain
fonte
1
isso não facilita a vida do hacker ?! porque agora, para acessar os recursos do servidor, precisamos tecnicamente da identificação do cliente, pois o servidor anexará o segredo à solicitação. estou esquecendo de algo?
Hudi Ilfeld
@HudiIlfeld Sim, está faltando alguma coisa: o cliente precisa fazer login no servidor. Enquanto ele não estiver logado, o servidor não retornará nada. Uma maneira de gerenciar isso é após o envio da credencial pela primeira vez, o servidor retorna um token de acesso ao cliente e, em seguida, o cliente envia esse token de acesso a cada solicitação futura. Existem muitas opções aqui.
Gudradain 17/04/19
4

Há uma nova extensão para o Tipo de concessão de código de autorização chamado Chave de prova para troca de código (PKCE) . Com isso, você não precisa de um segredo do cliente.

O PKCE (RFC 7636) é uma técnica para proteger clientes públicos que não usam um segredo do cliente.

É usado principalmente por aplicativos nativos e móveis, mas a técnica também pode ser aplicada a qualquer cliente público. Ele requer suporte adicional do servidor de autorização, portanto, é suportado apenas em determinados provedores.

de https://oauth.net/2/pkce/

Para mais informações, você pode ler a RFC 7636 completa ou esta breve introdução .

Johannes Filter
fonte
2

Aqui está algo para se pensar. O Google oferece dois métodos de OAuth ... para aplicativos da Web, nos quais você registra o domínio e gera uma chave exclusiva, e para aplicativos instalados, nos quais você usa a chave "anônimo".

Talvez eu tenha encoberto algo na leitura, mas parece que compartilhar a chave exclusiva do seu aplicativo da web com um aplicativo instalado é provavelmente mais seguro do que usar "anônimo" no método oficial de aplicativos instalados.

LetMyPeopleCode
fonte
2

Com o OAuth 2.0, você pode simplesmente usar o fluxo do lado do cliente para obter um token de acesso e usá-lo para autenticar todas as solicitações adicionais. Então você não precisa de um segredo.

Uma boa descrição de como implementar isso pode ser encontrada aqui: https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified#mobile-apps

Joel Richard
fonte
Desde que o serviço suporte "o fluxo do lado do cliente". Muitos não exigem, em vez disso, o ID do cliente e o segredo do cliente para obter esse token de acesso.
Damian Yerrick 31/01
0

Não tenho muita experiência com o OAuth - mas todas as solicitações não exigem apenas o token de acesso do usuário, mas também uma chave e um segredo do consumidor do aplicativo? Portanto, mesmo que alguém roube um dispositivo móvel e tente extrair dados dele, eles precisariam de uma chave e segredo do aplicativo também para poderem fazer alguma coisa.

Sempre achei que a intenção por trás do OAuth era que todos os Tom, Dick e Harry que tivessem um mashup não tivessem que armazenar suas credenciais do Twitter de maneira clara. Eu acho que resolve esse problema muito bem, apesar das limitações. Além disso, ele não foi realmente projetado com o iPhone em mente.

bpapa
fonte
Você está certo, o OAuth foi projetado principalmente com aplicativos da Web em mente e tenho certeza de que funciona bem para isso. Sim, você precisa do token e do segredo do consumidor para assinar cada solicitação, e o problema é onde armazenar o segredo. Se alguém rouba a chave de acesso, não é grande coisa porque pode ser revogada, mas se alguém obtém a chave do consumidor, todas as cópias do seu aplicativo foram comprometidas.
Felixyz
OAuth 1 exigia a assinatura de cada solicitação. OAuth 2 requer apenas o token de acesso. Ambos exigem a chave e o segredo ao adquirir um token.
Dick Hardt
0

Eu concordo com Felixyz. Embora o OAuth seja melhor que o Auth básico, ainda há um longo caminho a ser uma boa solução para aplicativos móveis. Estou brincando com o OAuth para autenticar um aplicativo para celular em um aplicativo do Google App Engine. O fato de você não poder gerenciar com segurança o segredo do consumidor no dispositivo móvel significa que o padrão é usar o acesso 'anônimo'.

A etapa de autorização do navegador da implementação do Google App Engine OAuth leva você a uma página onde contém texto como: "O site <some-site> está solicitando acesso à sua Conta do Google para os produtos listados abaixo"

YourApp (yourapp.appspot.com) - não afiliado ao Google

etc

Leva <some-site> do nome de domínio / host usado no URL de retorno de chamada que você fornece, o que pode ser qualquer coisa no Android se você usar um esquema personalizado para interceptar o retorno de chamada. Portanto, se você usar o acesso 'anônimo' ou o seu segredo do consumidor for comprometido, alguém poderá escrever um consumidor que engana o usuário a dar acesso ao seu aplicativo gae.

A página de autorização do Google OAuth também contém muitos avisos com três níveis de gravidade, dependendo de você estar usando chaves 'anônimas', secretas do consumidor ou públicas.

Coisas bastante assustadoras para o usuário médio que não é tecnicamente experiente. Não espero ter uma alta porcentagem de conclusão de inscrição com esse tipo de coisa no caminho.

Esta postagem do blog esclarece como os segredos do consumidor realmente não funcionam com aplicativos instalados. http://hueniverse.com/2009/02/should-twitter-discontinue-their-basic-auth-api/

Martin Bayly
fonte
0

Também estou tentando encontrar uma solução para autenticação OAuth móvel e armazenando segredos dentro do pacote de aplicativos em geral.

E uma idéia maluca me atingiu: a idéia mais simples é armazenar o segredo dentro do binário, mas ofuscado de alguma forma, ou, em outras palavras, você armazena um segredo criptografado. Então, isso significa que você precisa armazenar uma chave para descriptografar seu segredo, o que parece ter nos levado a um círculo completo. No entanto, por que não usar apenas uma chave que já esteja no sistema operacional, ou seja, é definida pelo sistema operacional e não pelo seu aplicativo.

Então, para esclarecer minha ideia, é que você escolha uma string definida pelo sistema operacional, não importa qual. Em seguida, criptografe seu segredo usando essa sequência como chave e armazene-a no seu aplicativo. Em seguida, durante o tempo de execução, descriptografe a variável usando a chave, que é apenas uma constante do SO. Qualquer hacker que espreite seu binário verá uma sequência criptografada, mas nenhuma chave.

Isso vai funcionar?

Daniel Thorpe
fonte
3
Bom pensamento, mas não. O cracker apenas veria o binário apontando para o endereço da constante do SO.
GrayB
0

Nenhuma dessas soluções impede um determinado hacker de farejar pacotes enviados de seu dispositivo móvel (ou emulador) para exibir o segredo do cliente nos cabeçalhos http.

Uma solução seria ter um segredo dinâmico composto por um carimbo de data / hora criptografado com uma chave de criptografia bidirecional e algoritmo privados. O serviço descriptografa o segredo e determina se o carimbo de data / hora é de +/- 5 minutos.

Dessa maneira, mesmo que o segredo seja comprometido, o hacker poderá usá-lo apenas por um período máximo de 5 minutos.

Maximvs
fonte
-2

Como outros já mencionaram, não deve haver problema real em armazenar o segredo localmente no dispositivo.

Além disso, você sempre pode confiar no modelo de segurança baseado no UNIX do Android: somente seu aplicativo pode acessar o que você escreve no sistema de arquivos. Basta escrever as informações no objeto SharedPreferences padrão do seu aplicativo.

Para obter o segredo, seria necessário obter acesso root ao telefone Android.

Christopher Orr
fonte
3
Como quem mencionou? Se você quer dizer o comentário do puxão, veja minha resposta secreta! = Chave de autenticação. O último pode ser armazenado com segurança, o primeiro não. Não sei sobre o Android, mas obter acesso root a um iPhone não é nada difícil. Observe que o segredo é o mesmo em todas as instâncias do aplicativo; portanto, um invasor só precisa obter acesso a um binário. E mesmo que não pudessem obter acesso root no dispositivo, eles poderiam colocar as mãos no binário de alguma outra forma e extrair o token secreto dele.
Felixyz
1
apenas para acrescentar que é muito fácil de raiz android telefones bem
kgutteridge