Chaves de API do usuário: duplicar client_id levará a erro interno no servidor

Ao chamar user-api-key/new com um client_id que já é usado por outro usuário, o fórum lançará um erro RecordNotUnique e falhará silenciosamente com um erro interno do servidor.

ActiveRecord::RecordNotUnique (PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint \"index_user_api_keys_on_client_id\"
DETAIL:  Key (client_id)=(893e0230d52455ea9b729334) already exists.
)
(eval):105:in `exec_params'
app/controllers/user_api_keys_controller.rb:66:in `create'

Isso pode querer falhar com algo menos silencioso, informando ao usuário que já existe uma chave de API com esse ID de cliente.

Embora isso me leve à segunda pergunta, as chaves de API de usuário devem se comportar assim? O ID do cliente deve ser exclusivo entre todos os usuários?

5 curtidas

Um rápido empurrão para visibilidade. Ainda estamos vendo esses aparecerem em nosso endpoint /logs com bastante frequência:

image

3 curtidas

Obrigado por relatar isso, tenho algumas perguntas para me ajudar a investigar.

Você pode fornecer um exemplo básico para que eu possa depurar isso localmente? Qual é o seu caso de uso para user-api-keys? Você está usando o aplicativo móvel Discourse Hub ou outra coisa?

1 curtida

Não tenho certeza do que você prefere como repro, mas este trecho de código PHP pode reproduzi-lo muito bem.

Código

// openssl genrsa -out keypair.pem 2048
$keypair = openssl_pkey_get_private(file_get_contents("keypair.pem"));

// Obter a chave pública
$public = openssl_pkey_get_details($keypair)["key"];

// Construir a consulta
$query = http_build_query([
    "auth_redirect" => "https://localhost/redirect",
    "application_name" => "Test repro",
    "client_id" => "7624a5376b7f52eb403a",
    "scopes" => "session_info",
    "nonce" => bin2hex(random_bytes(16)),
    "public_key" => $public
]);

$url = "https://forum.cfx.re/user-api-key/new?" . $query;
header("Location: " . $url);

A primeira e repetida autorização terá sucesso como o primeiro usuário, ao usá-la novamente para outro usuário sem alterar o client_id, ela falhará.
image

As chaves de API de usuário são usadas para permitir que o usuário use sua conta do fórum no cliente do jogo, para que eles possam postar do jogo. Também temos muitos usuários usando-as para autenticar com contas do fórum em seus próprios sites.

Enquanto o client_id deve ser único para os clientes do jogo, para que cada cliente seja listado como um cliente separado na tela de aplicativos. Para o caso de uso de sites, você desejará ter um client_id para que nem cada login seja listado separadamente.

3 curtidas

Gostaria de saber se isso foi resolvido

Houve alguma atualização sobre isso? Ainda não está claro se o client_id deve ser globalmente exclusivo em vez de por usuário.

1 curtida

Deve ser globalmente exclusivo.

Como isso deve ser implementado para casos de uso em que um site não possui seu próprio sistema de autenticação para usuários e não deve criar vários aplicativos de API de usuário?

2 curtidas

Definir um cookie? Ou determiná-lo com hash de algo que identifica o usuário (mais algo “secreto” para que partes externas não possam replicá-lo)

Se o aplicativo que autentica usuários deve ser usado em vários computadores e não possui nenhum dado de usuário antes da autenticação, isso é impossível.

Não entendo como isso se relaciona com o OP, já que ele descreve um caso em que um ID de cliente é compartilhado por vários usuários, onde o seu caso parece descrever um usuário que tem vários IDs de cliente.

É chamado de ID de cliente e não ID de usuário porque um usuário pode ter vários clientes!

Na maioria dos padrões como o OAuth, o ID do cliente é descrito como “identificador do aplicativo” e pode ser usado para todos os usuários (não apenas um), por exemplo, os logins sociais do seu fórum sempre usam o mesmo ID do cliente.

No entanto, como as chaves de API de usuário parecem ser projetadas principalmente para clientes como aplicativos Discourse, elas podem ter sido projetadas para serem exclusivas, seria bom saber se são.

Responder ao acima deixaria claro se há uma verificação faltando em user_api_keys.rb ou um índice incorreto no banco de dados. Porque atualmente essas solicitações geram um assustador erro 500 e aparecem em nosso endpoint /logs.

1 curtida

Alguma atualização sobre isso? Ainda vemos usuários enfrentando este problema.

1 curtida

O erro deveria ser melhor, sim, mas o client_id precisa ser único.

Quando você está enviando usuários dessa forma, deve gerar um ID exclusivo em sua chamada de API. O índice está correto, 1 usuário pode ter N client_ids.