Como posso projetar uma API JavaScript que permita scripts de domínio cruzado com segurança?

StackOverflow https://stackoverflow.com/questions/4060867

  •  27-09-2019
  •  | 
  •  

Pergunta

Eu gosto da maneira como a API do Google Maps é consumida, usando um script, mas estou preocupado:

Minha API é "semi-privada", isto é, acessível pela Internet, mas deve permitir a transmissão segura de dados e algum tipo de autenticação. Os dados devem permanecer privados sobre o fio e um consumidor não deve conseguir obter os dados de outro.

Como posso usar o SSL e algum tipo de autenticação para manter os dados seguros, mas ainda acessíveis "horizontalmente" a partir de uma página HTML simples, sem proxy do lado do servidor necessário? Eu preciso gerenciar chaves? Como as chaves serão postadas no servidor sem ser interceptada? Posso usar o OpenID (ou alguma outra autenticação de terceiros) para autenticar usuários da API, ou tenho que criar meu próprio mecanismo de autenticação? Estive por todo o Google e não consigo encontrar um bom guia para projetar e implantar minha API com segurança.

No momento, estou usando o descanso e o Ajax para consumi-los, mas as chamadas de domínio cruzado são impossíveis. Qualquer ajuda ou ponteiro na direção certa seria muito apreciada.

Foi útil?

Solução

Eu provavelmente usaria uma tag de script gerada dinamicamente com um URL SSL que incluía uma chave na sequência de consulta criptografada. O servidor usaria a chave privada para descriptografar o parâmetro da string de consulta e o script de retorno que incluía as informações relevantes (ou não, se a chave fosse inválida). Ou algo nesse sentido. Mas admito que eu realmente não tive que fazer isso na prática.

Eu também procuraria arte anterior, como o serviço S3 da Amazon.

Então:

  1. O usuário fornece segredo
  2. O código do lado do cliente usa a chave pública para criptografar o segredo
  3. JavaScript anexa a script tag que inclui o URL
  4. O servidor lida com a solicitação de script, descriptografa o segredo, verifica e envia de volta a resposta relevante.

Você pode precisar de dois ciclos, porque, caso contrário, a solicitação ao servidor pode ser reutilizada por meio de um ataque de homem no meio. Isso seria:

  1. JavaScript anexa a script tag que solicita uma chave única (provavelmente com algumas informações confusas, como o IP da fonte e alguma chave aleatória adicional)
  2. O servidor responde com uma chave única vinculada a esse IP
  3. O usuário fornece segredo
  4. O código do lado do cliente usa a chave pública para criptografar o segredo, incluindo a chave única do #1
  5. JavaScript anexa a script tag que inclui o URL
  6. O servidor lida com a solicitação de script, descriptografa o segredo, verifica e envia de volta a resposta relevante.
  7. A resposta pode muito bem ser criptografada (até certo ponto) usando a chave aleatória incluída no #1

Nenhum dos quais eu realmente fiz. (Ou eu tenho? Bwaa-ha-ha-ha ...) Fwiw.

Outras dicas

O OAuth pode ajudar nessa situação, fazendo com que o usuário faça login no aplicativo de terceiros e permitindo que seu aplicativo acesse o terceiro partido em seu nome usando um token de solicitação ao fazer solicitações XHR. http://oauth.net/documentation/getting-started/

========

O motivo do uso de um proxy do servidor se resume à política do mesmo origem incorporada aos navegadores da Web: http://en.wikipedia.org/wiki/same_origin_policy

Essencialmente, o navegador apenas permite que solicitações sejam feitas no endereço em que a página vem de (por exemplo, o Facebook.com só pode fazer solicitações ao Facebook.com URIS). Um proxy do lado do servidor resolve esse problema fazendo solicitações para servidores fora da origem atual. Os proxies do lado do servidor também são a melhor prática para fazer solicitações como essa.

Confira o projeto OpenSource JavaScript Forge. Ele fornece uma implementação JavaScript TLS que permite solicitações XHR de domínio cruzado seguro. Pode ser útil para você:

http://digitalbazaar.com/2010/07/20/javascript-tls-1/

http://digitalbazaar.com/2010/07/20/javascript-tls-2/

https://github.com/digitalbazaar/forge

Uma solução potencial:

  1. Configure um servidor Apache para executar seu site.
  2. Obtenha um certificado SSL para o seu site.
  3. Instale o mod Apache que vem com a Forge para configurar uma política de domínio cruzado que permite que outros sites acessem o seu.
  4. A implementação do TLS do host forge em seu site junto com o certificado do seu site no formato PEM.
  5. Diga a outros sites para incluir o JavaScript do seu site e use -o para fazer chamadas seguras para o seu site para fazer o que quiser.
  1. (3ª parte) Page usa oauth ou algo semelhante para autenticar o usuário e obter um token do seu servidor.
  2. A página carrega um iframe do seu servidor via SSL, passando o token para obter autenticação.
  3. O iframe pode se comunicar com segurança ao seu servidor via SSL
  4. Usar easyxdm Ou algo semelhante a se comunicar entre a página IFRAME e a terceira festa, usando uma API limitada do tipo RPC ou do tipo soquete que você cria.

Ou se você realmente não confia no terceiro - faça sua autenticação dentro do iframe (sem necessidade de OAuth, basta usar um formulário HTML simples) e comunicar qualquer coisa que a página externa precise saber sobre o usuário usando o easyXDM.

Não tenho muita certeza de qual é a pergunta exatamente, presumo que você esteja tentando fazer uma chamada do JSONP para [https://secure.com] para processar/exibir dados em [http://regular.com ]?

Os dois servidores podem falar um com o outro? Que tal algo como isso:

  1. O usuário faz login em [https://secure.com

  2. Após a autenticação, o Secure.com gera um token (vamos chamá-lo de Syntoken) e passa diretamente para regular.com (servidor para servidor), talvez como uma session_id, alguma mensagem arbitrária e uma cifra OTP (vamos chamar de sincipher) .

  3. Broswer recebe um cookie session_id e o seguro.com e redireciona o navegador para http://reguls.com/setcookieandredirect?session_id=blaBla&otpeNCRYPTEDSYNMESSAGE=BLABLA

  4. Regular.com procura OTP Cipher usando session_id como uma chave e descriptografa o OTPENPRYPTEDMESSAGE "BLBLA".

  5. Se a mensagem descriptografada corresponder à mensagem original no Syntoken, podemos verificar o usuário estar conectado [regular.com] e regular.com gera outro token (vamos chamá -lo de acktoken, lolz) e passa diretamente para [Secure.com], consistindo de session_id, alguma mensagem ACK arbitrária e uma cifra OTP diferente (vamos chamá -la de ackcipher).

  6. Regular.com envia ao navegador um cookie que consiste em otpencryptedackmessage (vamos nomear esse cookie "verificado_session").

  7. Termine de carregar a página.

A partir daí, você pode fazer chamadas do tipo jsonp para

https://secure.com/getscript.js?querery=dataname&verifiedtoken=(verifed_sessions_cookie_value)

Onde Secure.com/getscript.js levará o verificado, procure o ackcipher com base no cookie session_id original enviado por [Secure.com] como a chave e descriptografar o OTPENCRYpedackMessage. Se a mensagem descriptografada corresponder à mensagem ACK, renderize o arquivo de script.

É como um aperto de mão de três vias. O molho secreto é que os servidores precisam conversar diretamente entre si para passar as chaves secretas discreta. Você não precisa usar o mesmo session_id para os dois servidores, eu estava apenas usando isso como um ponto de referência fácil para encontrar uma maneira de acessar as cifras Syn/ACK OTP. As cifras devem estar completamente ocultas do público.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top