Visão geral
Estou procurando criar uma API (REST) para meu aplicativo. O objetivo inicial / principal será o consumo por aplicativos móveis (iPhone, Android, Symbian etc.). Estive estudando diferentes mecanismos de autenticação e autorização para APIs baseadas na Web (estudando outras implementações). Eu tenho minha cabeça envolvida na maioria dos conceitos fundamentais, mas ainda estou procurando orientação em algumas áreas. A última coisa que quero fazer é reinventar a roda, mas não estou encontrando soluções padrão que atendam aos meus critérios (no entanto, meus critérios podem ser equivocados, fique à vontade para criticar isso também). Além disso, quero que a API seja a mesma para todas as plataformas / aplicativos que a consomem.
oAuth
Vou seguir em frente e rejeitar minha objeção ao oAuth, pois sei que essa provavelmente será a primeira solução oferecida. Para aplicativos móveis (ou mais especificamente não relacionados à Web), parece errado deixar o aplicativo (acessar um navegador da Web) para autenticação. Além disso, não há como o navegador retornar o retorno de chamada ao aplicativo (especialmente entre plataformas). Conheço alguns aplicativos que fazem isso, mas parece errado e dá uma pausa no aplicativo UX.
Exigências
- O usuário insere o nome de usuário / senha no aplicativo.
- Toda chamada de API é identificada pelo aplicativo de chamada.
- As despesas gerais são reduzidas ao mínimo e o aspecto de autenticação é intuitivo para os desenvolvedores.
- O mecanismo é seguro para o usuário final (suas credenciais de logon não são expostas) e também para o desenvolvedor (suas credenciais de aplicativos não são expostas).
- Se possível, não exija https (de maneira alguma um requisito rígido).
Meus pensamentos atuais sobre implementação
Um desenvolvedor externo solicitará uma conta da API. Eles receberão um apikey e um sigilo. Toda solicitação exigirá no mínimo três parâmetros.
- apikey - dado ao desenvolvedor na inscrição
- timestamp - funciona como um identificador exclusivo para cada mensagem de um determinado apikey
- hash - um hash do timestamp + o apisecret
O apikey é necessário para identificar o aplicativo que emite a solicitação. O registro de data e hora age de maneira semelhante ao oauth_nonce e evita / mitiga ataques de repetição. O hash garante que a solicitação foi realmente emitida pelo proprietário do apikey fornecido.
Para solicitações autenticadas (feitas em nome de um usuário), ainda estou indeciso entre escolher uma rota access_token ou uma combinação de hash de nome de usuário e senha. De qualquer forma, em algum momento, será necessária uma combinação de nome de usuário / senha. Portanto, quando isso acontecer, um hash de várias informações (apikey, apisecret, timestamp) + a senha será usada. Eu adoraria comentários sobre esse aspecto. Para sua informação, eles teriam que fazer o hash da senha primeiro, já que eu não armazeno as senhas no meu sistema sem o hash.
Conclusão
Para sua informação, este não é um pedido de como criar / estruturar a API em geral, apenas como lidar com a autenticação e autorização somente dentro de um aplicativo.
Perguntas aleatórias sobre pensamentos / bônus
Para APIs que exigem apenas um apikey como parte da solicitação, como você evita que alguém que não seja o proprietário do apikey consiga ver o apikey (desde que foi enviado de forma clara) e faz solicitações excessivas para empurrá-los além dos limites de uso? Talvez eu esteja pensando demais sobre isso, mas não deveria haver algo para autenticar que uma solicitação foi verificada para o proprietário do apikey? No meu caso, esse era o objetivo do apisecret, ele nunca é mostrado / transmitido sem ser hash.
Falando em hashes, e o MD5 vs hmac-sha1? Realmente importa quando todos os valores são misturados com dados suficientemente longos (isto é, apisecret)?
Antes, eu estava pensando em adicionar um sal por usuário / linha ao hash de senha dos meus usuários. Se eu fizesse isso, como o aplicativo poderia criar um hash correspondente sem conhecer o sal usado?
Respostas:
A maneira como estou pensando em fazer a parte de login disso nos meus projetos é:
Antes de efetuar o login, o usuário solicita um
login_token
do servidor. Eles são gerados e armazenados no servidor mediante solicitação e provavelmente têm uma vida útil limitada.Para efetuar login no aplicativo, calcula o hash da senha do usuário e, em seguida, faz o hash da senha com o
login_token
valor de obter um valor; eles retornamlogin_token
o hash combinado e o hash.O servidor verifica o
login_token
que ele gerou, removendo-o da sua lista delogin_token
s válidos . O servidor então combina seu hash armazenado da senha do usuário comlogin_token
oe garante que ele corresponda ao token combinado enviado. Se corresponder, você autenticou seu usuário.As vantagens disso são que você nunca armazena a senha do usuário no servidor, a senha nunca é passada de forma clara, o hash da senha é passado apenas de forma clara na criação da conta (embora possa haver maneiras de contornar isso), e deve ser protegido contra ataques de repetição, pois ele
login_token
é removido do banco de dados em uso.fonte
São muitas perguntas em uma, acho que muitas pessoas não conseguiram ler até o fim :)
Minha experiência na autenticação de serviços da Web é que as pessoas geralmente fazem o excesso de engenharia e os problemas são os mesmos que você encontraria em uma página da Web. Possíveis opções muito simples incluem https para a etapa de login, retornam um token, exigem que ele seja incluído em solicitações futuras. Você também pode usar a autenticação básica http e apenas passar coisas no cabeçalho. Para aumentar a segurança, gire / expire os tokens com frequência, verifique se as solicitações são provenientes do mesmo bloco IP (isso pode ficar confuso, pois os usuários móveis se movem entre as células), combinado com a chave da API ou similar. Como alternativa, execute a etapa "solicitar chave" do oauth (alguém já sugeriu isso em uma resposta anterior e é uma boa idéia) antes de autenticar o usuário e use-a como uma chave necessária para gerar o token de acesso.
Uma alternativa que eu ainda não usei, mas já ouvi falar muito como alternativa ao oAuth, compatível com dispositivos, é o xAuth . Dê uma olhada e, se você usá-lo, eu ficaria realmente interessado em saber quais são suas impressões.
Para o hash, o sha1 é um pouco melhor, mas não se preocupe - o que os dispositivos puderem implementar facilmente (e rapidamente no sentido de desempenho) provavelmente está bom.
Espero que ajude, boa sorte :)
fonte
Então, o que você procura é algum tipo de mecanismo de autenticação no servidor que lide com os aspectos de autenticação e autorização de um aplicativo móvel?
Supondo que esse seja o caso, então eu abordaria da seguinte maneira (mas apenas porque eu sou um desenvolvedor Java, então um cara de C # faria isso de maneira diferente):
O serviço de autenticação e autorização RESTful
A biblioteca / aplicativo de segurança do lado do cliente
Então agora que a visão de 30.000 pés está completa, como você faz isso? Bem, não é tão difícil criar um sistema de autenticação e autorização com base nas tecnologias listadas no lado do servidor com um cliente de navegador. Em combinação com HTTPS, as estruturas fornecerão um processo seguro com base em um token compartilhado (geralmente apresentado como um cookie) gerado pelo processo de autenticação e usado sempre que o usuário desejar fazer algo. Esse token é apresentado pelo cliente ao servidor sempre que ocorre uma solicitação.
No caso do aplicativo móvel local, parece que você está procurando uma solução que faça o seguinte:
Faça o que fizer, não tente inventar seu próprio protocolo de segurança ou use a segurança pela obscuridade. Você nunca poderá escrever um algoritmo melhor para isso do que aqueles que estão disponíveis no momento e são gratuitos. Além disso, as pessoas confiam em algoritmos conhecidos. Portanto, se você disser que sua biblioteca de segurança fornece autorização e autenticação para aplicativos móveis locais usando uma combinação de tokens criptografados SSL, HTTPS, SpringSecurity e AES, você terá imediatamente credibilidade no mercado.
Espero que isso ajude e boa sorte com seu empreendimento. Se você quiser obter mais informações, informe-me - escrevi alguns aplicativos da Web baseados em Spring Security, ACLs e similares.
fonte
O Twitter solucionou o problema de aplicativo externo no oAuth, suportando uma variante que eles chamam de xAuth . Infelizmente, já existem vários outros esquemas com esse nome, portanto pode ser confuso resolver o problema.
O protocolo é oAuth, exceto que ignora a fase do token de solicitação e simplesmente emite imediatamente um par de token de acesso após o recebimento de um nome de usuário e senha. (Começando na etapa E aqui .) Essa solicitação e resposta inicial devem ser protegidas- está enviando o nome de usuário e a senha em texto sem formatação e recebendo de volta o token de acesso e o token secreto. Depois que o par de tokens de acesso for configurado, se a troca de tokens inicial foi por meio do modelo oAuth ou do modelo xAuth é irrelevante para o cliente e o servidor pelo restante da sessão. Isso tem a vantagem de poder aproveitar a infraestrutura existente do oAuth e ter quase a mesma implementação para aplicativos móveis / web / desktop. A principal desvantagem é que o aplicativo recebe acesso ao nome de usuário e senha do cliente, mas parece que seus requisitos exigem essa abordagem.
De qualquer forma, gostaria de concordar com a sua intuição e a de vários outros respondentes aqui: não tente criar algo novo do zero. Os protocolos de segurança podem ser fáceis de iniciar, mas sempre são difíceis de executar, e quanto mais complicados eles se tornam, menor a probabilidade de seus desenvolvedores de terceiros poderem implementar contra eles. Seu protocolo hipotético é muito semelhante ao o (x) Auth - api_key / api_secret, nonce, sha1 hashing - mas em vez de poder usar uma das muitas bibliotecas existentes que seus desenvolvedores precisarão usar por conta própria.
fonte
Cheguei tarde demais para a festa, mas eu queria mencionar alguns pontos adicionais a serem considerados para qualquer pessoa interessada nessa questão. Eu trabalho para uma empresa que cria soluções de segurança de API móvel ( approov ), portanto toda essa área é definitivamente relevante para meus interesses.
Para começar, a coisa mais importante a considerar ao tentar proteger uma API móvel é quanto vale para você . A solução certa para um banco é diferente da solução certa para alguém que apenas faz as coisas por diversão.
Na solução proposta, você menciona que serão necessários no mínimo três parâmetros:
A implicação disso é que, para algumas chamadas de API, não é necessário nome de usuário / senha. Isso pode ser útil para aplicativos em que você não deseja forçar um login (navegando em lojas on-line, por exemplo).
Esse é um problema ligeiramente diferente do da autenticação do usuário e é mais parecido com a autenticação ou atestado do software. Não há usuário, mas você ainda deseja garantir que não haja acesso malicioso à sua API. Então você usa seu segredo da API para assinar o tráfego e identificar o código que acessa a API como genuíno. O possível problema com esta solução é que você precisará revelar o segredo em todas as versões do aplicativo. Se alguém puder extrair o segredo, poderá usar sua API, personificando seu software, mas fazendo o que quiser.
Para combater essa ameaça, há várias coisas que você pode fazer, dependendo da importância dos dados. A ofuscação é uma maneira simples de dificultar a extração do segredo. Existem ferramentas que farão isso por você, mais ainda no Android, mas você ainda precisa ter um código que gere seu hash e um indivíduo suficientemente qualificado pode sempre chamar a função que faz o hash diretamente.
Outra forma de atenuar contra o uso excessivo de uma API que não requer um login é estrangular o tráfego e potencialmente identificar e bloquear endereços IP suspeitos. A quantidade de esforço que você deseja fazer dependerá em grande parte da validade dos seus dados.
Além disso, você pode facilmente começar a entrar no domínio do meu trabalho diário. De qualquer forma, é outro aspecto da segurança de APIs que eu acho importante e queria sinalizar.
fonte