Práticas recomendadas para gerar tokens OAuth?

100

Sei que a especificação do OAuth não especifica nada sobre a origem do código ConsumerKey, ConsumerSecret, AccessToken, RequestToken, TokenSecret ou Verifier, mas estou curioso para saber se há alguma prática recomendada para criar tokens significativamente seguros (especialmente Token / Combinações secretas).

A meu ver, existem algumas abordagens para criar os tokens:

  1. Basta usar bytes aleatórios, armazenar no banco de dados associado ao consumidor / usuário
  2. Faça hash de alguns dados específicos do usuário / consumidor, armazene no banco de dados associado ao consumidor / usuário
  3. Criptografar dados específicos do usuário / consumidor

As vantagens de (1) são o banco de dados ser a única fonte de informação que parece mais segura. Seria mais difícil executar um ataque contra (2) ou (3).

O hash dos dados reais (2) permitiria a regeneração do token a partir de dados presumivelmente já conhecidos. Pode não fornecer nenhuma vantagem para (1), já que precisaria armazenar / pesquisar de qualquer maneira. Mais uso da CPU do que (1).

Criptografar dados reais (3) permitiria descriptografar para saber as informações. Isso exigiria menos armazenamento e potencialmente menos pesquisas do que (1) e (2), mas potencialmente menos seguro também.

Existem outras abordagens / vantagens / desvantagens que devem ser consideradas?

EDITAR: outra consideração é que DEVE haver algum tipo de valor aleatório nos tokens, pois deve haver a capacidade de expirar e reemitir novos tokens, de modo que não deve ser composto apenas de dados reais.

Perguntas para Acompanhamento :

Existe um comprimento mínimo de token para tornar significativamente criptograficamente seguro? Pelo que entendi, segredos de token mais longos criariam assinaturas mais seguras. Este entendimento está correto?

Há vantagens em usar uma codificação específica em relação a outra de uma perspectiva de hashing? Por exemplo, vejo muitas APIs usando codificações hexadecimais (por exemplo, strings GUID). No algoritmo de assinatura OAuth, o Token é usado como uma string. Com uma string hexadecimal, o conjunto de caracteres disponível seria muito menor (mais previsível) do que, digamos, com uma codificação Base64. Parece-me que, para duas strings de comprimento igual, aquela com o conjunto de caracteres maior teria uma distribuição de hash melhor / mais ampla. Isso me parece que melhoraria a segurança. Esta suposição está correta?

A especificação OAuth levanta exatamente esse problema em 11.10 Entropia de Segredos .

mckamey
fonte
Por que a criptografia? O hashing não é bom o suficiente? Se apenas o hash é bom o suficiente para a senha, não deveria ser ainda melhor para tokens de acesso mais longos?
AlikElzin-kilaka
Já se passaram 7,5 anos desde que fiz a pergunta. Sinceramente, não consigo me lembrar.
mckamey
1
Lendo novamente, hashing e criptografia foram duas abordagens diferentes sugeridas. A criptografia permitiria ao servidor obter algumas informações sem uma consulta ao banco de dados. Foi uma troca entre muitas.
mckamey

Respostas:

93

OAuth não diz nada sobre o token, exceto que tem um segredo associado a ele. Portanto, todos os esquemas que você mencionou funcionariam. Nosso token evoluiu conforme os sites ficam maiores. Aqui estão as versões que usamos antes,

  1. Nosso primeiro token é um BLOB criptografado com nome de usuário, segredo do token e expiração, etc. O problema é que não podemos revogar tokens sem qualquer registro no host.

  2. Então, nós o alteramos para armazenar tudo no banco de dados e o token é simplesmente um número aleatório usado como chave para o banco de dados. Ele tem um índice de nome de usuário, então é fácil listar todos os tokens de um usuário e revogá-lo.

  3. Recebemos poucas atividades de hackers. Com o número aleatório, temos que ir ao banco de dados para saber se o token é válido. Então, voltamos ao BLOB criptografado novamente. Desta vez, o token contém apenas o valor criptografado da chave e a expiração. Assim, podemos detectar tokens inválidos ou expirados sem acessar o banco de dados.

Alguns detalhes de implementação que podem ajudá-lo,

  1. Adicione uma versão ao token para que possa alterar o formato do token sem quebrar os existentes. Todos os nossos tokens têm primeiro byte como versão.
  2. Use a versão segura de URL de Base64 para codificar o BLOB para que você não precise lidar com os problemas de codificação de URL, o que torna a depuração mais difícil com a assinatura OAuth, porque você pode ver a sequência de base com codificação tripla.
ZZ Coder
fonte
2
Excelente, obrigado. A ideia da versão é boa. Eu tenho o URL-friendly Base64 funcionando, mas gostaria de ter uma codificação estritamente alfanumérica para uma leitura ainda mais fácil.
mckamey
Não tinha pensado nisso antes, muito interessante! Eu estava planejando usar o cache de chaves da APC para manter a carga de acesso fora do banco de dados antes de ler isso. Ainda não tenho certeza se isso pode não ser muito mais lento do que uma pesquisa de memória compartilhada do APC (pelo menos na 2ª, 3ª, etc ... solicitação em um intervalo de tempo razoável).
Philzen