我使用oauth-1.0a节点包来使用Zotero实现OAuth。
我正在使用在zotero-oauth-示例回购中找到的代码。
运行上面提到的回购中的代码是有效的。我认为我的实现不起作用,因为我已经将回购中的单个函数划分为两个函数->示例repo不处理重定向客户端和处理回调。
我认为问题是:--我认为实例化两个不同的OAuth对象(一个是步骤1,另一个在步骤3)正在破坏一些东西。注意,我暂时保留了步骤1的hash_function中产生的散列,这是在步骤3中使用的。
我对OAuth不熟悉。你对我该尝试什么有什么建议吗?
1)请求令牌(服务器)
// omitting includes packages
const tokenRequestConfig = {
url: 'https://www.zotero.org/oauth/request',
method: 'POST',
data: {
oauth_callback: baseURL, // redirect to baseURL
},
},
initZoteroIntegration = async () => {
let oAuthHash;
const oauth = OAuth({
consumer: {
key: process.env.ZOTERO_APP_CLIENT_KEY,
secret: process.env.ZOTERO_APP_CLIENT_SECRET,
},
signature_method: 'HMAC-SHA1',
hash_function(base_string, key) {
oAuthHash = crypto.createHmac('sha1', key).update(base_string).digest('base64');
return oAuthHash;
},
}),
tokenRequestResponse = await fetch('https://www.zotero.org/oauth/request', {
headers: oauth.toHeader(oauth.authorize(tokenRequestConfig)),
method: 'post',
}),
tokenRequestData = await tokenRequestResponse.text(),
obj = {};
tokenRequestData.replace(/([^=&]+)=([^&]*)/g, (m, key, value) => {
obj[decodeURIComponent(key)] = decodeURIComponent(value);
});
const oAuthToken = obj.oauth_token,
oAuthTokenSecret = obj.oauth_token_secret,
url = `https://www.zotero.org/oauth/authorize?oauth_token=${oAuthToken}&library_access=1¬es_access=1&write_access=1&all_groups=write`;
/* the url should be returned to the client */
return ({
url,
oAuthToken,
oAuthTokenSecret,
oAuthHash,
});
};
2)客户端被定向到Zotero应用程序登录并授权权限。
3)令牌交换(服务器)
// omitting includes packages
const confirmIntegration = async ({oAuthToken, oAuthTokenSecret, oAuthVerifier, oAuthHash}) => {
const oauth = OAuth({
consumer: {
key: process.env.ZOTERO_APP_CLIENT_KEY,
secret: process.env.ZOTERO_APP_CLIENT_SECRET,
},
signature_method: 'HMAC-SHA1',
hash_function() {
return oAuthHash;
},
}),
tokenExchangeConfig = {
url: `https://www.zotero.org/oauth/access?oauth_token=${oAuthToken}`,
method: 'POST',
data: {
oauth_verifier: oAuthVerifier,
oauth_callback: baseURL,
},
},
tokenExchangeResponse = await fetch(`https://www.zotero.org/oauth/access?oauth_token=${oAuthToken}`, {
headers: oauth.toHeader(oauth.authorize(tokenExchangeConfig, {
public: oAuthToken,
secret: oAuthTokenSecret,
})),
method: 'post',
}),
tokenExchangeData = await tokenExchangeResponse.text();
try {
const username = tokenExchangeData.match(/username=(\w+)/)[1],
userID = tokenExchangeData.match(/userID=([0-9]+)/)[1],
userAPIKey = tokenExchangeData.match(/oauth_token_secret=([a-zA-Z0-9]+)/)[1];
return {
username,
userID,
userAPIKey,
};
} catch (e) {
// TODO throw some error
return null;
}
};
在‘令牌交换’步骤上,我得到一个带有401状态代码(“未经授权”)的响应。
tokenExchangeResponse.text()正在返回oauth_problem=signature_invalid
这是原始输出:
"https_sig_error=1&z_debug_sbs=POST&https%3A%2F%2Fwww.zotero.org%2Foauth%2Faccess&oauth_consumer_key%3D9a016199db19772cb220%26oauth_nonce%3DDs3iXBVWF4izl1qfX0mk0JXIvZkl7N5o%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1545238813%26oauth_token%3D6f6ade01f30625feeb36%26oauth_verifier%3D02469ed77305b02befd8%26oauth_version%3D1.0&oauth_problem=signature_invalid&debug_sbs=POST&https%3A%2F%2Fwww.zotero.org%2Foauth%2Faccess&oauth_consumer_key%3D9a016199db19772cb220%26oauth_nonce%3DDs3iXBVWF4izl1qfX0mk0JXIvZkl7N5o%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1545238813%26oauth_token%3D6f6ade01f30625feeb36%26oauth_verifier%3D02469ed77305b02befd8%26oauth_version%3D1.0"*Fix Ok,我找到了一个解决方案。我使用node-cache在有限的时间内缓存OAuth对象。
感谢您@tnajdek澄清了OAuth的上述用法是问题所在。
发布于 2018-12-19 22:36:20
注意,我暂时保留了步骤1的hash_function中产生的散列,这是在步骤3中使用的。
这不管用。
hash_function构造函数的OAuth参数采用base_string (它是请求的序列化摘要)和key来生成其结果。base_string和key在步骤1和步骤3之间都不同,但是hash_function返回步骤1中缓存的结果,作为步骤3中完全不同的参数base_string和key的结果。
我不知道您的应用程序的其余部分是什么样子,但是我只创建一次OAuth实例,并在初始请求中和服务器请求处理例程中的回调请求中重用它。如果这不是一个选项,您可以使用相同的参数重新创建OAuth,并且它应该工作得很好。
https://stackoverflow.com/questions/53859439
复制相似问题