Steam OpenID 签名验证
Steam OpenID Signature Validation
这个问题我已经有一段时间了。我正在尝试添加一个“通过 Steam 登录”按钮,该按钮在登录时不仅会检索用户 ID,还会验证签名。 Steam 使用 OpenID 2.0。
我已遵循文档 here。我仔细地遵循了这些步骤,花了我一天中的大部分时间来试图解决这个问题。我的代码是这样的:
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
(key:value 对字符串)给出预期输出:
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
不匹配。请注意,我在上述 key:value 对字符串的末尾使用了 \n
,因为这是我解释文档的方式。
注意我之所以需要身份验证,是因为我想将Steam帐户与我网站上的帐户关联起来,通过Steam登录后,您就可以完全访问您在我网站上的帐户,这意味着用户不能简单地输入另一个用户 ID 并访问他们的帐户(重放攻击)是非常重要的。因此,我需要以某种方式验证签名。
我以前从未使用过 OpenID,所以请原谅我的任何愚蠢错误。我强烈建议阅读上面链接的文档,以便您可以验证我所做的是正确的。
亲切的问候,
初始请求
将您的 Steam 登录按钮link设为
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:这是 Steam 将在成功登录后使用附加的查询字符串参数重定向到的 URL。
openid.realm URL Steam 会要求用户信任。当用户在 Steam 登录页面时,它将显示为这样的消息:使用您的 Steam 帐户登录{openid.realm}。请注意,{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 将 return 像这样的 text/plain
响应:
ns:http://specs.openid.net/auth/2.0
is_valid:true
若true
用户有效,false
无效。请注意,此调用只会 return true
一次 并且使用相同参数的后续调用将始终 return false。从这里,您可以决定如何维护正在登录的用户(例如创建一个唯一的 cookie)和 return 重定向响应到您网站的主页、他们单击 Steam 登录按钮之前的最后一页或用户详情页等...
这个问题我已经有一段时间了。我正在尝试添加一个“通过 Steam 登录”按钮,该按钮在登录时不仅会检索用户 ID,还会验证签名。 Steam 使用 OpenID 2.0。
我已遵循文档 here。我仔细地遵循了这些步骤,花了我一天中的大部分时间来试图解决这个问题。我的代码是这样的:
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
(key:value 对字符串)给出预期输出:
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
不匹配。请注意,我在上述 key:value 对字符串的末尾使用了 \n
,因为这是我解释文档的方式。
注意我之所以需要身份验证,是因为我想将Steam帐户与我网站上的帐户关联起来,通过Steam登录后,您就可以完全访问您在我网站上的帐户,这意味着用户不能简单地输入另一个用户 ID 并访问他们的帐户(重放攻击)是非常重要的。因此,我需要以某种方式验证签名。
我以前从未使用过 OpenID,所以请原谅我的任何愚蠢错误。我强烈建议阅读上面链接的文档,以便您可以验证我所做的是正确的。
亲切的问候,
初始请求
将您的 Steam 登录按钮link设为
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:这是 Steam 将在成功登录后使用附加的查询字符串参数重定向到的 URL。
openid.realm URL Steam 会要求用户信任。当用户在 Steam 登录页面时,它将显示为这样的消息:使用您的 Steam 帐户登录{openid.realm}。请注意,{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 将 return 像这样的 text/plain
响应:
ns:http://specs.openid.net/auth/2.0
is_valid:true
若true
用户有效,false
无效。请注意,此调用只会 return true
一次 并且使用相同参数的后续调用将始终 return false。从这里,您可以决定如何维护正在登录的用户(例如创建一个唯一的 cookie)和 return 重定向响应到您网站的主页、他们单击 Steam 登录按钮之前的最后一页或用户详情页等...