问题
I am trying to implement Twitter login with my MERN application. Following twitter tutorials, i understand that all request should be signed with an OAuth headers. If i use postman, i enter my credentials (Consumer Key, Consumer Secret) in the authorization tab and the call works. The things is that postman transform the Consumer secret into and oauth_signature before sending the call. Now i want to do this workflow in Nodejs. All tutorials online use complicated passport strategies and the use of request module which is depricated. I understand that to generate oauth_signature one would have to generate an oauth_nonce and then do: Percent encode every key and value that will be signed. Sort the list of parameters alphabetically [1] by encoded key [2]. For each key/value pair: Append the encoded key to the output string. Append the ‘=’ character to the output string. Append the encoded value to the output string. If there are more key/value pairs remaining, append a ‘&’ character to the output string.
I am sure doing all this would be reinventing the wheel and am pretty sure there is a module that does this step specifically without all the passport and authentication (which is already done in my app) i simply need to sign my twitter requests like Postman does nothing more.
I tried the following but it seems am still doing something wrong
var axios = require('axios');
const jsSHA = require('jssha/sha1');
//Am i using the right library??
const callBackUL = 'https%3A%2F%2F127.0.0.1%3A3000%2Flogin';
var oauth_timestamp = Math.round(new Date().getTime() / 1000.0);
const nonceObj = new jsSHA('SHA-1', 'TEXT', { encoding: 'UTF8' });
nonceObj.update(Math.round(new Date().getTime() / 1000.0));
const oauth_nonce = nonceObj.getHash('HEX');
const endpoint = 'https://api.twitter.com/oauth/request_token';
const oauth_consumer_key = process.env.TWITTER_API_KEY;
const oauth_consumer_secret = process.env.TWITTER_API_SECRET;
var requiredParameters = {
oauth_consumer_key,
oauth_nonce,
oauth_signature_method: 'HMAC-SHA1',
oauth_timestamp,
oauth_version: '1.0'
};
const sortString = requiredParameters => {
var base_signature_string = 'POST&' + encodeURIComponent(endpoint) + '&';
var requiredParameterKeys = Object.keys(requiredParameters);
for (var i = 0; i < requiredParameterKeys.length; i++) {
if (i == requiredParameterKeys.length - 1) {
base_signature_string += encodeURIComponent(
requiredParameterKeys[i] +
'=' +
requiredParameters[requiredParameterKeys[i]]
);
} else {
base_signature_string += encodeURIComponent(
requiredParameterKeys[i] +
'=' +
requiredParameters[requiredParameterKeys[i]] +
'&'
);
}
}
return base_signature_string;
};
const sorted_string = sortString(requiredParameters);
console.log('Sorted string:', sorted_string);
const signing = (signature_string, consumer_secret) => {
let hmac;
if (
typeof signature_string !== 'undefined' &&
signature_string.length > 0
) {
//console.log('String OK');
if (
typeof consumer_secret !== 'undefined' &&
consumer_secret.length > 0
) {
// console.log('Secret Ok');
const secret = consumer_secret + '&';
var shaObj = new jsSHA('SHA-1', 'TEXT', {
hmacKey: { value: secret, format: 'TEXT' }
});
shaObj.update(signature_string);
hmac = encodeURIComponent(shaObj.getHash('B64'));
//var hmac_sha1 = encodeURIComponent(hmac);
}
}
return hmac;
};
const signed = signing(sorted_string, oauth_consumer_secret);
console.log(signed);
var data = {};
var config = {
method: 'post',
url: endpoint,
headers: {
Authorization: `OAuth oauth_consumer_key=${process.env.TWITTER_API_KEY},oauth_signature_method="HMAC-SHA1",oauth_timestamp=${oauth_timestamp},oauth_nonce=${oauth_nonce},oauth_version="1.0",oauth_callback=${callBackUL},oauth_consumer_secret=${signed}`,
'Content-Type': 'application/json'
},
data: data
};
try {
const response = await axios(config);
console.log(JSON.stringify(response.data));
} catch (err) {
console.log(err.response.data);
}
next();
});
回答1:
SOLVED
var axios = require('axios');
const jsSHA = require('jssha/sha1');
const callBackUL = 'https%3A%2F%2F127.0.0.1%3A3000%2Flogin';
var oauth_timestamp = Math.round(new Date().getTime() / 1000.0);
const nonceObj = new jsSHA('SHA-1', 'TEXT', { encoding: 'UTF8' });
nonceObj.update(Math.round(new Date().getTime() / 1000.0));
const oauth_nonce = nonceObj.getHash('HEX');
const endpoint = 'https://api.twitter.com/oauth/request_token';
const oauth_consumer_key = process.env.TWITTER_API_KEY;
const oauth_consumer_secret = process.env.TWITTER_API_SECRET;
var requiredParameters = {
oauth_callback: callBackUL,
oauth_consumer_key,
oauth_nonce,
oauth_signature_method: 'HMAC-SHA1',
oauth_timestamp,
oauth_version: '1.0'
};
const sortString = requiredParameters => {
var base_signature_string = 'POST&' + encodeURIComponent(endpoint) + '&';
var requiredParameterKeys = Object.keys(requiredParameters);
for (var i = 0; i < requiredParameterKeys.length; i++) {
if (i == requiredParameterKeys.length - 1) {
base_signature_string += encodeURIComponent(
requiredParameterKeys[i] +
'=' +
requiredParameters[requiredParameterKeys[i]]
);
} else {
base_signature_string += encodeURIComponent(
requiredParameterKeys[i] +
'=' +
requiredParameters[requiredParameterKeys[i]] +
'&'
);
}
}
return base_signature_string;
};
const sorted_string = sortString(requiredParameters);
console.log('Sorted string:', sorted_string);
const signing = (signature_string, consumer_secret) => {
let hmac;
if (
typeof signature_string !== 'undefined' &&
signature_string.length > 0
) {
//console.log('String OK');
if (
typeof consumer_secret !== 'undefined' &&
consumer_secret.length > 0
) {
// console.log('Secret Ok');
const secret = encodeURIComponent(consumer_secret) + '&';
var shaObj = new jsSHA('SHA-1', 'TEXT', {
hmacKey: { value: secret, format: 'TEXT' }
});
shaObj.update(signature_string);
hmac = encodeURIComponent(shaObj.getHash('B64'));
}
}
return hmac;
};
const signed = signing(sorted_string, oauth_consumer_secret);
console.log(signed);
var data = {};
var config = {
method: 'post',
url: endpoint,
headers: {
Authorization: `OAuth oauth_consumer_key=${process.env.TWITTER_API_KEY},oauth_nonce=${oauth_nonce},oauth_signature=${signed},oauth_signature_method="HMAC-SHA1",oauth_timestamp=${oauth_timestamp},oauth_version="1.0",oauth_callback=${callBackUL}`,
'Content-Type': 'application/json'
},
data: data
};
try {
const response = await axios(config);
console.log(JSON.stringify(response.data));
} catch (err) {
console.log(err.response.data);
}
next();
来源:https://stackoverflow.com/questions/64767401/oauth-1-0-transform-consumer-secret-into-an-oauth-signature