私は、OAuth1.0をよく理解し、Twitter Passportで問題をデバッグするために、Node.jsにTwitterログインを構築しようとしていましたが、 。Twitter OAuth1.0 failed - "Authorization Required"
ドキュメントから、ユーザー認証はトークンの要求から始まります。
私は既に自分のTwitterアプリを作成し、コールバックURLを設定しました。私が経験している問題は、私の署名を作成し、私の最初の要求を提出するときに起こります。
ヘッダーを異なる順番に並べると、400 Bad Request
エラーが発生します。しかし、以下の設定では、401 Authorization Required
エラーが発生しています。私はどこに私のエラーが見つかりませんか分かりません。私はそれが署名そのものとエンコーディングに関係していると感じます。
私はここでどんな方向にも大いに感謝します。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent - - ポリフィルへ
私のエンコーディングについては
エンコーディング、私はここで見つけたコードのブロックを使用していました。コードは次のように見えた:
function fixedEncodeURIComponent(str) {
return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
return '%' + c.charCodeAt(0).toString(16);
});
}
しかし、私は結果がencodeURIComponent()
を介して実行された文字列であるOAuth npm package
、コードベース内のこのかなり独断コメントに出くわした:
// Fix the mismatch between OAuth's RFC3986's and Javascript's beliefs in what is right and wrong ;)
return result.replace(/\!/g, "%21")
.replace(/\'/g, "%27")
.replace(/\(/g, "%28")
.replace(/\)/g, "%29")
.replace(/\*/g, "%2A");
私はを選びました後者。
NTPタイム
私はまた、クライアントの時間とサーバー時間の間の可能な切断を述べたので、私はntp-client
NPMパッケージを実装し、いくつかのSOの質問をお読みください。
関連するコード
私は何を参照してくださいお知らせください(注:私はmoment
、axios
、crypto
をインポートだ、と私はすべての私の関数をエクスポートするよ、私はちょうどここにこれらの行を除外):
server.js
const nonce = require('./utils/nonce')();
const timestamp = require('./utils/timestamp')();
Promise.all([nonce, timestamp]).then(function(values) {
const axios = require('axios');
const percentalizedURIComponent = require('./utils/percentalize');
const oauth_url = 'https://api.twitter.com/oauth/request_token'
const oauth_method = 'POST';
const oauth_callback = process.env.TWITTER_CALLBACK;
const oauth_consumer_key = process.env.TWITTER_CONSUMER_KEY;
const oauth_nonce = values[0];
const oauth_signature_method = 'HMAC-SHA1';
const oauth_timestamp = values[1];
const oauth_version = '1.0';
const oauth_signature = require('./utils/signature')(oauth_url, oauth_method,
[process.env.TWITTER_CONSUMER_SECRET],
{ oauth_callback, oauth_consumer_key, oauth_nonce, oauth_signature_method,
oauth_timestamp, oauth_version });
console.log({ oauth_signature: oauth_signature });
axios({
method: oauth_method,
url: oauth_url,
headers: {
Authorization: "OAuth oauth_callback=\"" +
percentalizedURIComponent(oauth_callback) + "\", oauth_consumer_key=\"" +
percentalizedURIComponent(oauth_consumer_key) + "\", oauth_nonce=\"" +
percentalizedURIComponent(oauth_nonce) + "\", oauth_signature=\"" +
percentalizedURIComponent(oauth_signature) + "\", oauth_signature_method=\"" +
percentalizedURIComponent(oauth_signature_method) + "\", oauth_timestamp=\"" +
percentalizedURIComponent(oauth_timestamp) + "\", oauth_version=\"" +
percentalizedURIComponent(oauth_version) + "\"",
Host: 'api.twitter.com'
}
}).then(function(response) {
console.log({ tokenResponse: response })
}).catch(function(error) {
console.error({ twitterTokenError: error })
});
}).catch(function(err) { console.error({ createSignatureError: err }) });
percentalize.js(符号化)
function percentalizedURIComponent(str) {
return encodeURIComponent(str).replace(/\!/g, "%21")
.replace(/\'/g, "%27")
.replace(/\(/g, "%28")
.replace(/\)/g, "%29")
.replace(/\*/g, "%2A");
}
timestamp.js
function timestamp() {
return new Promise(function(resolve, reject) {
ntpClient.getNetworkTime("pool.ntp.org", 123, function(err, date) {
if (err)
return reject(err);
return resolve(parseInt(moment(date).format("X")));
});
})
}
signature.js
/**
* Function that takes in raw data and outputs a cryptographic signature
* @param {String} url - endpoint of api being called
* @param {String} method - HTTP method called on url
* @param {Object[]} keys - array of signing keys
* @param {Object} oauth - headers to be encoded into singature
* @returns {String} hashed signature of data being sent to api
*/
function createSignature(url, method, keys = [], oauth = {}) {
const headers = Object.keys(oauth);
const paramString = headers.map(function(header) {
return percentalizedURIComponent(header) + '=' + percentalizedURIComponent(oauth[header]);
}).join("&");
const baseString = method.toUpperCase() + '&' + percentalizedURIComponent(url) + '&' + percentalizedURIComponent(paramString);
const hmac = crypto.createHmac(algorithm, keys.join('&'));
hmac.update(baseString);
return hmac.digest('base64');
}
ありがとうございます。週末にこれを見てみましょう、あなたに戻ってください! – wlh