사용자 API 키: 중복된 client_id로 인해 내부 서버 오류 발생

client_id가 이미 다른 사용자에 의해 사용 중인 경우 user-api-key/new를 호출하면 포럼은 RecordNotUnique 오류를 발생시키고 내부 서버 오류로 조용히 실패합니다.

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'

이 경우 해당 클라이언트 ID를 가진 API 키가 이미 존재한다는 사실을 사용자에게 알리는 방식으로, 좀 더 명확하게 실패하도록 개선하는 것이 좋을 것 같습니다.

그러나 이는 두 번째 질문으로 이어집니다. 사용자 API 키가 이러한 방식으로 동작하도록 설계된 것인가요? 클라이언트 ID는 모든 사용자 간에 고유해야 하나요?

5개의 좋아요

가시성을 높이기 위해 간단히 알립니다. 여전히 /logs 엔드포인트에서 이러한 오류가 꽤 자주 발생하고 있습니다:

image

3개의 좋아요

이 문제를 보고해 주셔서 감사합니다. 다만, 이 문제를 조사하는 데 도움이 될 몇 가지 질문이 있습니다.

로컬에서 디버깅할 수 있도록 이 문제에 대한 기본적인 재현 방법을 알려 주시겠습니까? 사용자 API 키를 사용하는 용도는 무엇이며, discourse 허브 모바일 앱을 사용 중이신가요, 아니면 다른 도구를 사용 중이신가요?

1개의 좋아요

어떤 형태의 재현 방법을 선호하시는지 확실하지는 않지만, 아래 PHP 코드 조각으로 잘 재현됩니다.

코드
<?php

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

// 공개 키 가져오기
$public = openssl_pkey_get_details($keypair)["key"];

// 쿼리 생성
$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);

첫 번째 인증 및 반복 인증은 첫 번째 사용자로 성공하지만, client_id를 변경하지 않고 다른 사용자에게 다시 사용하면 실패합니다.
image

User API 키는 사용자가 게임 클라이언트에서 포럼 계정을 사용할 수 있도록 허용하는 데 사용되며, 이를 통해 게임 내에서 게시물을 올릴 수 있습니다. 또한 많은 사용자가 자신의 웹사이트에서 포럼 계정으로 인증하는 데 이를 사용하기도 합니다.

게임 클라이언트의 경우 클라이언트 ID는 고유해야 하므로, 각 클라이언트가 앱 화면에서 별도의 클라이언트로 나열됩니다. 웹사이트 사용 사례의 경우, 각 로그인이 별도로 나열되지 않도록 하나의 클라이언트 ID를 사용하는 것이 좋습니다.

3개의 좋아요

이 문제가 해결되었는지 궁금해서요

이 문제에 대해 업데이트가 있나요? client_id가 사용자별로 고유해야 하는지, 아니면 전역적으로 고유해야 하는지 아직 명확하지 않습니다.

1개의 좋아요

전역적으로 고유해야 합니다.

웹사이트가 자체 사용자 인증 시스템을 갖추지 않았고, 여러 사용자 API 애플리케이션을 생성해서는 안 되는 사용 사례에서 이를 어떻게 구현해야 할까요?

2개의 좋아요

쿠키를 설정할까요? 아니면 사용자를 식별하는 정보(외부 주체가 이를 복제할 수 없도록 하는 “비밀” 정보)을 해싱하여 결정할까요?

[quote=“Michael - Communiteq, post:13, topic:260995, username:michaeld”]
사용자를 식별하는 정보(외부 주체가 이를 복제할 수 없도록 하는 “비밀” 정보 포함)를 해싱하여 결정할 수도 있습니다.
[/quote]사용자를 인증하는 애플리케이션이 여러 대의 컴퓨터에서 사용되어야 하고, 인증 전에 사용자 데이터가 전혀 없는 경우 이는 불가능합니다.

OP에서는 여러 사용자가 동일한 클라이언트 ID를 공유하는 상황을 설명하고 있는데, 질문자의 경우는 한 사용자가 여러 클라이언트 ID를 가지고 있는 것으로 보이는데, 이 둘이 어떻게 관련이 있는지 이해가 되지 않습니다.

클라이언트 ID는 사용자 ID가 아니라 클라이언트 ID라고 불리는 이유는, 한 사용자가 여러 클라이언트를 가질 수 있기 때문입니다!

OAuth와 같은 대부분의 표준에서 client id는 "앱 식별자(app identifier)"로 설명되며, 특정 사용자 한 명이 아닌 모든 사용자에게 사용할 수 있습니다. 예를 들어, 포럼의 소셜 로그인은 항상 동일한 client id를 사용합니다.

그러나 사용자 API 키는 Discourse 앱과 같은 클라이언트를 위해 주로 설계된 것으로 보이며, 고유하게(unique) 설계되었을 가능성이 있습니다. 실제로 그런지 여부에 대해 알 수 있으면 좋겠습니다.

위 질문에 대한 답변이 있으면 user_api_keys.rb에 누락된 검증이 있는지, 아니면 데이터베이스에 잘못된 인덱스가 있는지 명확해질 것입니다. 현재 해당 요청은 무서운 500 오류를 발생시키고 있으며, /logs 엔드포인트에 표시됩니다.

1개의 좋아요

이 문제에 대해 업데이트가 있나요? 여전히 이 문제를 겪는 사용자들을 보고 있습니다.

1개의 좋아요

에러 메시지는 더 좋아야 하지만, client_id는 고유해야 합니다.

이 방식으로 사용자를 전송할 때는 API 호출에서 고유한 id를 생성해야 합니다. 인덱스는 올바른 것이며, 1명의 사용자는 N개의 client id를 가질 수 있습니다.