Como garantir que minha API REST responda apenas a solicitações geradas por clientes confiáveis, no meu caso, meus próprios aplicativos móveis? Quero impedir que solicitações indesejadas venham de outras fontes. Não quero que os usuários preencham uma chave serial ou o que seja, isso deve acontecer nos bastidores, na instalação e sem a necessidade de interação do usuário.
Até onde eu sei, o HTTPS é apenas para validar o servidor com o qual você está se comunicando e quem ele diz que é. Claro que vou usar HTTPS para criptografar os dados.
Existe uma maneira de conseguir isso?
Atualização: o usuário pode executar ações somente leitura, que não exigem que o usuário esteja conectado, mas também pode executar ações de gravação, que exigem que o usuário esteja conectado (Autenticação por token de acesso). Nos dois casos, quero que a API responda a solicitações provenientes apenas de aplicativos móveis confiáveis.
A API também será usada para registrar uma nova conta através do aplicativo móvel.
Atualização 2: Parece que existem várias respostas para isso, mas sinceramente não sei qual sinalizar como resposta. Alguns dizem que isso pode ser feito, outros dizem que não.
Respostas:
Você não pode.
Você nunca pode verificar uma entidade, qualquer entidade , seja uma pessoa, cliente de hardware ou cliente de software. Você só pode verificar se o que eles estão dizendo está correto e assumir honestidade .
Por exemplo, como o Google sabe que estou fazendo login na minha conta do Gmail? Eles simplesmente me pedem um nome de usuário e uma senha, verificam isso e assumem honestidade porque quem mais teria essas informações? Em algum momento, o Google decidiu que isso não era suficiente e adicionou uma verificação comportamental (procurando um comportamento estranho), mas que ainda depende da pessoa para fazer o comportamento e depois a validação do comportamento .
Isso é exatamente o mesmo com a validação do cliente. Você só pode validar o comportamento do cliente, mas não o próprio cliente.
Portanto, com o SSL, você pode verificar se o Cliente possui um certificado válido ou não. Assim, basta instalar o aplicativo, obter o certificado e executar todo o novo código.
Então a pergunta é: por que isso é tão crítico? Se essa é uma preocupação real, eu questionaria sua escolha de um cliente gordo. Talvez você deva usar um aplicativo da Web (para não precisar expor sua API).
Consulte também: Derrotando a validação de certificado SSL para aplicativos Android
e: Quão seguros são os certificados SSL do cliente em um aplicativo móvel?
fonte
Tenho certeza de que você se sente à vontade para lidar com logins de usuários e com comunicações via SSL; portanto, vou me concentrar no que acho a parte mais interessante da pergunta: como garantir que suas ações somente leitura - que não exigem que o usuário seja autenticado - são aceitos apenas em seus próprios aplicativos clientes?
Antes de mais nada, existe o lado negativo que o fNek sugeriu em uma resposta anterior - seus aplicativos clientes estão nas mãos de usuários potencialmente hostis. Eles podem ser examinados, suas comunicações inspecionadas, seu código desmontado. Nada do que vou sugerir permitirá garantir que alguém não faça engenharia reversa no seu cliente e abuse da API REST. Mas deve colocar uma barreira na frente de qualquer tentativa casual.
De qualquer forma, uma abordagem comum é:
Por exemplo, imagine um
GET
pedido de/products/widgets
Digamos que o segredo do cliente seja "OH_HAI_I_IZ_SECRET"
Concatene o verbo HTTP, a URL e o segredo:
E pegue um hash SHA-1 disso:
Em seguida, envie-o, para que a solicitação seja:
Por fim, para impedir que alguém reproduza solicitações individuais pelo menos, use também um carimbo de data e hora e adicione-o aos parâmetros e ao hash. por exemplo, agora, no horário Unix, é 1384987891. Adicione isso à concatenação:
Hash que:
E envia:
O servidor verificará o hash e também verificará se o registro de data e hora está atualizado (por exemplo, dentro de 5 minutos para permitir que os relógios não estejam perfeitamente sincronizados)
Aviso! Como você está falando de aplicativos para dispositivos móveis, há um risco definido de que o telefone de alguém tenha o relógio errado. Ou fuso horário errado. Ou alguma coisa. A adição de tempo ao hash provavelmente quebrará alguns usuários legítimos; portanto, use essa idéia com cautela.
fonte
Para qualquer pessoa interessada, no Android, você PODE verificar se a solicitação que recebeu foi enviada do seu aplicativo.
Em resumo, quando você faz o upload do seu aplicativo para o Google, assina-o, com uma chave exclusiva conhecida apenas por você (e pelo Google).
O processo de verificação é (ish) assim:
o blog completo que explica e como implementá-lo pode ser encontrado aqui: http://android-developers.blogspot.co.il/2013/01/verifying-back-end-calls-from-android.html
fonte
Ok, vale a pena mencionar antes de começar que, para a maioria das aplicações, isso é um exagero. Para a maioria dos casos de uso, simplesmente ter um único certificado e / ou token válido é mais que suficiente. Se envolver algo difícil como descompilar o aplicativo, mesmo a maioria dos hackers não se incomodará, a menos que você forneça alguns dados muito valiosos. Mas ei, qual é a graça nessa resposta?
Então, o que você pode fazer é configurar a criptografia assimétrica, como as assinaturas digitais usadas para assinar programas. Cada aplicativo pode ter um certificado individual emitido por uma única CA e verificado quando o usuário se conecta. (no primeiro registro ou na primeira instalação) Quando esse certificado é autenticado, você pode proteger ainda mais seu aplicativo registrando esse certificado como válido para um determinado identificador de dispositivo (como o Android ID )
fonte
Como o @Morons mencionado em sua resposta, é muito difícil verificar a entidade na outra extremidade da conexão.
A maneira mais simples de fornecer algum nível de autenticidade é fazer com que o servidor verifique algum segredo que somente a entidade real saberia. Para um usuário, esse pode ser um nome de usuário e uma senha. Para um software em que não há usuário, você pode incorporar um segredo.
O problema com essas abordagens é que você precisa confiar no cliente. Se alguém reverter seu aplicativo ou roubar sua senha, ele poderá fingir ser você.
Você pode tomar medidas para dificultar a extração das informações secretas, ofuscando-as no executável. Ferramentas como o ProGuard, que é um ofuscador para Java, podem ajudar com isso. Não sei muito sobre ofuscação em outras linguagens, mas provavelmente existem ferramentas semelhantes. O uso de uma conexão TLS ajuda a impedir que as pessoas bisbilhotem seu tráfego, mas não impede um ataque MITM. A fixação pode ajudar a resolver esse problema.
Eu trabalho para uma empresa chamada CriticalBlue (divulgação completa!) Que possui um produto chamado Approov que tenta solucionar esse problema de confiança. Atualmente, ele funciona para Android / iOS e fornece um mecanismo para nossos servidores verificarem a integridade do aplicativo cliente. Isso é feito fazendo com que o cliente calcule uma resposta a um desafio aleatório. O cliente precisa calcular a resposta usando atributos do pacote de aplicativos instalados que são difíceis de falsificar e incluem alguns sofisticados mecanismos anti-adulteração.
Ele retorna um token que você pode enviar como prova de autenticidade para sua API.
A diferença importante com essa abordagem é que, embora seja possível desativar a verificação de autenticidade no cliente, se você o fizer, não obterá o token de autenticação, precisará verificar seu aplicativo com o servidor. A biblioteca também está fortemente acoplada às características do executável em que está, portanto, seria muito difícil incorporá-lo em um aplicativo falso e fazê-lo funcionar.
Existe uma análise de custo / benefício que qualquer desenvolvedor de API deve fazer para decidir qual a probabilidade de alguém tentar invadir sua API e qual o custo. Uma simples verificação secreta no aplicativo evita ataques triviais, mas proteger-se contra um invasor mais determinado é provavelmente consideravelmente mais complicado e potencialmente caro.
fonte
O SSL protegerá o canal de comunicação.
O login bem-sucedido emitirá um token de autenticação pela conexão criptografada.
O token de autenticação será passado para sua API REST em todas as solicitações subsequentes.
fonte
Não seria muito seguro, mas você poderia adicionar algum tipo de código secreto ou até uma assinatura digital. Desvantagem: ele deve ser incluído no aplicativo, o que facilita a sua obtenção se você souber o que faz.
fonte
De fato, você pode usar o SSL para autenticar o cliente e o servidor. Ou, dito de forma diferente, "sim, você pode usar certificados de cliente".
Você precisará ...
Você pode fazer com que o aplicativo móvel armazene o certificado onde quiser. Como você deseja autenticação específica do aplicativo, considere armazenar o certificado em um local protegido do disco (no Android, você pode criar uma tabela "config" no banco de dados SQLite e uma linha para o seu certificado e outra para a sua chave privada) .
fonte