Проверка подписи Steam OpenID

У меня уже давно есть эта проблема. Я пытаюсь добавить кнопку «Войти через Steam», которая при входе в систему не только извлекает идентификатор пользователя, но и проверяет подпись. Steam использует OpenID 2.0.

Я следил за документацией здесь. Я тщательно следовал этим шагам, потратив большую часть своего дня на попытки понять это. Мой код таков:

let s = data['openid.signed'].split(',');
let x = Buffer.from(s.map(x => `${x}:${data['openid.' + x]}`).join('\n') + '\n', 'utf8');
let c = crypto.createHash('sha1').update(x).digest('base64');
console.log(x.toString('utf8')); // This is the key:value string
console.log(c); // This is the final result; the generated signature

Где данные — это ответ, полученный от провайдера OpenID. Регистрация x (строка пары ключ:значение) дает ожидаемый результат:

signed:signed,op_endpoint,claimed_id,identity,return_to,response_nonce,assoc_handle
op_endpoint:https://steamcommunity.com/openid/login
claimed_id:https://steamcommunity.com/openid/id/765611981[1234567]
identity:https://steamcommunity.com/openid/id/765611981[1234567]
return_to:http://127.0.0.1:8000/resolve
response_nonce:2018-12-01T17:53: [some_hash]=
assoc_handle:1234567890

Однако мой сгенерированный хэш c не соответствует данной подписи openid.sig. Обратите внимание, что я использую \n в конце приведенной выше строки пары ключ:значение, поскольку именно так я интерпретировал документацию.

Примечание. Причина, по которой мне нужна аутентификация, заключается в том, что я хочу связать учетную запись Steam с учетной записью на своем веб-сайте, а вход через Steam дает вам полный доступ к вашей учетной записи на моем веб-сайте, что означает, что Крайне важно, чтобы пользователь не мог просто ввести идентификатор другого пользователя и получить доступ к своей учетной записи (атака с повтором). Из-за этого мне нужно как-то проверить подпись.

Я никогда раньше не работал с OpenID, так что извините за мои глупые ошибки. Я настоятельно рекомендую прочитать документацию, указанную выше, чтобы вы могли убедиться, что я делаю правильно.

С уважением,


person troffaholic    schedule 01.12.2018    source источник
comment
Я вижу только аутентификацию HMAC. HMAC требует предварительно установленного секретного ключа и состоит не только из хэша.   -  person Maarten Bodewes    schedule 02.12.2018
comment
Ты прав. Я понял это через некоторое время. Однако я не уверен, какой секретный ключ использовать. У меня есть ключ API Steam, но я не уверен, предназначен ли он для этого. Вместо этого я придумал эту строку crypto.createHmac('sha1', 'SteamAPIKey32Chars').update(x).digest('base64');, но она все еще не дает предполагаемого хэша.   -  person troffaholic    schedule 02.12.2018
comment
Жаль, что документация в Steam такая плохая. Nonces включает двоеточие, которое, согласно документации OpenID, не является допустимым символом. В конце концов, все сводится к реализации Steam, о которой я ничего не знаю. Достаточно одного примера!   -  person troffaholic    schedule 02.12.2018
comment
@troffaholic ты когда-нибудь решал эту проблему?   -  person jjjjjjjjjjjjjjjjjjjj    schedule 19.02.2020


Ответы (1)


Первоначальный запрос

Сделайте ссылку на кнопку входа в Steam на

https://steamcommunity.com/openid/login?openid.ns=http://specs.openid.net/auth/2.0&openid.claimed_id=http://specs.openid.net/auth/2.0/identifier_select&openid.identity=http://specs.openid.net/auth/2.0/identifier_select&openid.return_to=https://mywebsite.com&openid.realm=https://mywebsite.com&openid.mode=checkid_setup

и замените параметры строки запроса openid.return_to и openid.realm.

openid.return_to: это URL-адрес, на который Steam перенаправит после успешного входа с добавленными параметрами строки запроса.

openid.realm URL-адрес, который Steam попросит пользователя доверять. Когда пользователь находится на странице входа в Steam, это будет отображаться в виде сообщения: Войдите в {openid.realm}, используя свою учетную запись Steam. Обратите внимание, что {openid.realm} не связан со Steam или Valve.

Обработка ответа

После успешного входа Steam перенаправит на URL-адрес, например

https://mywebsite.com/?openid.ns=http://specs.openid.net/auth/2.0&openid.mode=id_res&openid.op_endpoint=https://steamcommunity.com/openid/login&openid.claimed_id=https://steamcommunity.com/openid/id/76561198002516729&openid.identity=https://steamcommunity.com/openid/id/76561198002516729&openid.return_to=https:/%mywebsite.com&openid.response_nonce=2020-08-27T04:44:16Zs4DPZce8qc+iPCe8JgQKB0BiIDI=&openid.assoc_handle=1234567890&openid.signed=signed,op_endpoint,claimed_id,identity,return_to,response_nonce,assoc_handle&openid.sig=W0u5DRbtHE1GG0ZKXjerUZDUGmc=

Чтобы подтвердить пользователя, сделайте вызов из своего бэкенда, чтобы https://steamcommunity.com/openid/login скопировать каждый параметр строки запроса из этого ответа, за одним исключением: замените &openid.mode=id_res на &openid.mode=check_authentication. Таким образом, последний вызов будет по этому URL-адресу:

https://steamcommunity.com/openid/login?openid.ns=http://specs.openid.net/auth/2.0&openid.mode=check_authentication&openid.op_endpoint=https://steamcommunity.com/openid/login&openid.claimed_id=https://steamcommunity.com/openid/id/76561198002516729&openid.identity=https://steamcommunity.com/openid/id/76561198002516729&openid.return_to=https://mywebsite.com&openid.response_nonce=2020-08-28T04:44:16Zs4DPZce8qc+iPCe8JgQKB0BiIDI=&openid.assoc_handle=1234567890&openid.signed=signed,op_endpoint,claimed_id,identity,return_to,response_nonce,assoc_handle&openid.sig=W0u5DRbtHE1GG0ZKXjerUZDUGmc=

Steam вернет ответ text/plain следующим образом:

ns:http://specs.openid.net/auth/2.0
is_valid:true

Если true пользователь действителен, false недействителен. Обратите внимание, что этот вызов вернет true один раз, а последующие вызовы с теми же параметрами всегда будут возвращать false. Отсюда вы можете решить, как сохранить пользователя, вошедшего в систему (например, создать уникальный файл cookie), и вернуть ответ перенаправления на что-то вроде домашней страницы вашего сайта, последней страницы перед тем, как они нажали кнопку входа в Steam, или страницу сведений о пользователе и т. д. ...

person Matthew Steven Monkan    schedule 29.08.2020
comment
Я продолжал нажимать Server denied check_authentication в python, этот ответ помог найти, что не так. Этот ответ может проверить ОП с помощью curl. +1 - person foxyblue; 08.01.2021