Autorização e Autenticação da API REST (web + mobile)

Eu li sobre oAuth, Amazon REST API, HTTP Basic / Digest e assim por diante, mas não consigo obter tudo em “peça única”. Esta é provavelmente a situação mais próxima – Criando uma API para aplicativos móveis – Autenticação e Autorização

Gostaria de criar o site-serviço centrado na API. Então (no início) eu teria uma API no centro e no site (PHP + MySQL) iria se conectar via cURL , Android e iPhone através das suas interfaces de rede. Então, 3 clientes principais – 3 chaves da API. E qualquer outro desenvolvedor também pode desenvolver-se através da interface da API e eles terão sua própria chave de API. As ações da API serão aceitas / rejeitadas com base no status do usuário, se eu for um administrador, posso excluir qualquer coisa, etc., todos os outros podem manipular apenas seus dados locais (conta).

Primeiro, autorização – devo usar oAuth + xAuth ou a minha implementação de algum tipo de meu próprio (consulte http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/RESTAuthentication.html?r=9197 )? Como eu entendi, no usuário do serviço Amazon é == usuário da API (tem a chave da API) . No meu serviço, eu preciso separar os usuários / contas padrão (aquele que se registrou no site) e as Contas do desenvolvedor (quem deveria ter sua chave da API).

Então eu primeiro precisaria autorizar a chave da API e, em seguida, autenticar o próprio usuário . Se eu usar o esquema da Amazon para verificar as chaves da API do desenvolvedor (autorizar seu aplicativo), qual sheme devo usar para a autenticação do usuário?

Eu leio sobre como obter um token via api.example.org/auth depois (via HTTPS , HTTP Basic) postando meu nome de usuário e senha e, em seguida, encaminhe-o em cada solicitação seguinte. Como gerenciar tokens se eu estiver logado simultaneamente no Android e em um site ? E quanto ao ataque do homem no meio, se eu estiver usando SSL somente na primeira solicitação (quando o nome de usuário e a senha são transmitidos) e apenas HTTP em todos os outros? Não é um problema neste exemplo Senha protegendo um serviço REST?

Como sempre, a melhor maneira de proteger uma chave não é transmiti-la.

Dito isto, normalmente usamos um esquema, onde cada “chave API” tem duas partes: uma identificação não secreta (por exemplo, 1234) e uma chave secreta (por exemplo, byte [64]).

  • Se você der uma chave da API, guarde-a (salgada e hash) no database do seu serviço.
  • Se você distribuir contas de usuário (protegido por senha), armazene as senhas (salgadas e hash) no database do seu serviço

Agora, quando um consumidor primeiro acessa sua API, para se conectar, tê-lo

  • Enviar um parâmetro de “nome de usuário” (“john.doe” não secreto)
  • Enviar um parâmetro “APIkeyID” (“1234”, não secreto)

e devolvê-lo

  • os sais do seu database (caso um dos parâmetros esteja errado, devolva um pouco de sal repetitivo – por exemplo, sha1 (nome de usuário + “notverysecret”).
  • O timestamp do servidor

O consumidor deve armazenar o sal para a duração da session para manter as coisas rápidas e suaves, e ele deve calcular e manter o tempo compensado entre o cliente e o servidor.

O consumidor agora deve calcular os hashes salgados da chave API e senha. Desta forma, o consumidor tem exatamente os mesmos hashes para a senha e a chave da API, como o que está armazenado no seu database, mas sem qualquer coisa que tenha passado pelo fio.

Agora, quando um consumidor acessa subseqüentemente sua API, para fazer um trabalho real, faça com ele

  • Enviar um parâmetro de “nome de usuário” (“john.doe” não secreto)
  • Enviar um parâmetro “APIkeyID” (“1234”, não secreto)
  • Enviar um parâmetro “RequestSalt” (byte [64], random, não secreto)
  • Envie um parâmetro “RequestTimestamp” (calculado a partir do tempo do cliente e do deslocamento conhecido)
  • Enviar um parâmetro “RequestToken” (hash (passwordhash + request_salt + request_timestamp + apikeyhash))

O servidor não deve aceitar timestamps mais do que dizer 2 segundos no passado, para tornar isso seguro contra um ataque de repetição.

O servidor agora pode calcular o mesmo hash (passwordhash + request_salt + request_timestamp + apikeyhash) como o cliente e com certeza, que

  • o cliente conhece a chave API,
  • o cliente conhece a senha correta