oauth 1.0 を介して 500px API への認証済みリクエストを行う必要があります。私はこのガイドに従っていて、説明されているワークフローをいくつかの異なる方法で実装しましたが、取得し続けていstatusCode: 401...
ます.
ここで私がこれまでに試したこと:
試み #1:
likePhoto (id) {
let crypto = Npm.require('crypto'),
consumerKey = '-',
consumerSecret = '-',
accessToken = Meteor.user().services.Fivehundredpx.accessToken,
accessTokenSecret = Meteor.user().services.Fivehundredpx.accessTokenSecret,
url = 'https://api.500px.com/v1/photos/231034201/vote?vote=1',
date = new Date,
method = 'POST';
// Note that the keys are in alphabetical order
let reqObj = {
oauth_consumer_key: consumerKey,
oauth_nonce: Math.random().toString(36).replace(/[^a-z]/, '').substr(2),
oauth_signature_method: 'HMAC-SHA1',
oauth_timestamp: Math.floor(date.getTime() / 1000),
oauth_token: accessToken,
oauth_version: '1.0'
};
// construct a param=value& string and uriEncode
let paramsStr = '';
for (let i in reqObj) {
paramsStr += "&" + i + "=" + reqObj[i];
}
// yank off that first "&"
paramsStr = paramsStr.substr(1);
let sigBaseStr = method + "&" + encodeURIComponent(url) + "&" + encodeURIComponent(paramsStr);
consumerSecret += "&" + accessTokenSecret;
let hashedBaseStr = crypto.createHmac('sha1', consumerSecret).update(sigBaseStr).digest('base64');
// Add oauth_signature to the request object
reqObj.oauth_signature = encodeURIComponent(hashedBaseStr);
let authorization = 'OAuth ';
for (let i in reqObj) {
authorization += i + '="'+ reqObj[i] + '",';
}
console.log(authorization);
Meteor.http.call(method, url,
{headers: {
Authorization: authorization,
}},
function (error, result) {
console.log(result || error);
});
}
試み #2:
likePhoto (id) {
const oauthSignature = require('oauth-signature');
let date = new Date;
let httpMethod = 'POST',
url = 'https://api.500px.com/v1/photos/231034201/vote?vote=1',
parameters = {
oauth_consumer_key : '',
oauth_nonce : Math.random().toString(36).replace(/[^a-z]/, '').substr(2),
oauth_signature_method : 'HMAC-SHA1',
oauth_timestamp : Math.floor(date.getTime() / 1000),
oauth_token : Meteor.user().services.Fivehundredpx.accessToken,
oauth_version : '1.0',
},
consumerSecret = '',
tokenSecret = Meteor.user().services.Fivehundredpx.accessTokenSecret,
// generates a RFC 3986 encoded, BASE64 encoded HMAC-SHA1 hash
encodedSignature = oauthSignature.generate(httpMethod, url, parameters, consumerSecret, tokenSecret),
// generates a BASE64 encode HMAC-SHA1 hчash
signature = oauthSignature.generate(httpMethod, url, parameters, consumerSecret, tokenSecret,
{ encodeSignature: false});
// construct a param=value& string and uriEncode
let paramsStr = '';
for (let i in parameters) {
paramsStr += "&" + i + "=" + parameters[i];
}
// Add oauth_signature to the request object
parameters.oauth_signature = encodedSignature;
let authorization = 'OAuth ';
for (let i in parameters) {
authorization += i + '="'+ parameters[i] + '",';
}
console.log(authorization);
HTTP.call(httpMethod, url,
{
headers: {
'Authorization': authorization,
}
},
function (error, result) {
console.log(result || error);
});
}
試行 #3:
function oAuthBaseString(method, url, params, key, token, timestamp, nonce) {
return method
+ '&' + percentEncode(url)
+ '&' + percentEncode(genSortedParamStr(params, key, token, timestamp, nonce));
}
function oAuthSigningKey(consumer_secret, token_secret) {
return consumer_secret + '&' + token_secret;
}
function oAuthSignature(base_string, signing_key) {
var signature = hmac_sha1(base_string, signing_key);
return percentEncode(signature);
}
// Percent encoding
function percentEncode(str) {
return encodeURIComponent(str).replace(/[!*()']/g, (character) => {
return '%' + character.charCodeAt(0).toString(16);
});
}
// HMAC-SHA1 Encoding, uses jsSHA lib
var jsSHA = require('jssha');
function hmac_sha1(string, secret) {
let shaObj = new jsSHA("SHA-1", "TEXT");
shaObj.setHMACKey(secret, "TEXT");
shaObj.update(string);
let hmac = shaObj.getHMAC("B64");
return hmac;
}
// Merge two objects
function mergeObjs(obj1, obj2) {
for (var attr in obj2) {
obj1[attr] = obj2[attr];
}
return obj1;
}
// Generate Sorted Parameter String for base string params
function genSortedParamStr(params, key, token, timestamp, nonce) {
// Merge oauth params & request params to single object
let paramObj = mergeObjs(
{
oauth_consumer_key : key,
oauth_nonce : nonce,
oauth_signature_method : 'HMAC-SHA1',
oauth_timestamp : timestamp,
oauth_token : token,
oauth_version : '1.0'
},
params
);
// Sort alphabetically
let paramObjKeys = Object.keys(paramObj);
let len = paramObjKeys.length;
paramObjKeys.sort();
// Interpolate to string with format as key1=val1&key2=val2&...
let paramStr = paramObjKeys[0] + '=' + paramObj[paramObjKeys[0]];
for (var i = 1; i < len; i++) {
paramStr += '&' + paramObjKeys[i] + '=' + percentEncode(decodeURIComponent(paramObj[paramObjKeys[i]]));
}
return paramStr;
}
likePhoto (id) {
const btoa = require('btoa');
// Get acces keys
const consumerKey = '-',
consumerSecret = '-',
accessToken = Meteor.user().services.Fivehundredpx.accessToken,
accessTokenSecret = Meteor.user().services.Fivehundredpx.accessTokenSecret;
// timestamp as unix epoch
let timestamp = Math.round(Date.now() / 1000);
// nonce as base64 encoded unique random string
let nonce = btoa(consumerKey + ':' + timestamp);
// generate signature from base string & signing key
let httpMethod = 'POST';
let baseUrl = 'https://api.500px.com/v1/photos/231034201/vote?vote=1';
let reqParams = '';
let baseString = oAuthBaseString(httpMethod, baseUrl, reqParams, consumerKey, accessToken, timestamp, nonce);
let signingKey = oAuthSigningKey(consumerSecret, accessTokenSecret);
let signature = oAuthSignature(baseString, signingKey);
// return interpolated string
let authorization = 'OAuth ' +
'oauth_consumer_key="' + consumerKey + '", ' +
'oauth_nonce="' + nonce + '", ' +
'oauth_signature="' + signature + '", ' +
'oauth_signature_method="HMAC-SHA1", ' +
'oauth_timestamp="' + timestamp + '", ' +
'oauth_token="' + accessToken + '", ' +
'oauth_version="1.0"';
console.log(authorization);
HTTP.call(httpMethod, baseUrl,
{headers: {
Authorization: authorization,
}},
function (error, result) {
console.log(result || error);
});
}
このAPI クライアントをテストに使用していますが、すべてのリクエストは正常に機能しています。同様のワークフローとコードを使用して別の OAuth 1.0 認証リクエストを実装したところ、うまくいきましたが、私の側では間違いであるはずです。
エラーメッセージ:
{
statusCode: 401,
content: '',
headers:
{ date: 'Mon, 09 Oct 2017 05:27:17 GMT',
'content-type': 'text/html',
'transfer-encoding': 'chunked',
connection: 'close',
status: '401 Unauthorized',
'x-xss-protection': '1; mode=block',
'x-content-type-options': 'nosniff',
'cache-control': 'no-cache',
'set-cookie':
[ 'device_uuid=4b97d884-b24e-413c-90ee-60d11e7f2ad7; path=/; expires=Fri, 09 Oct 2037 05:27:17 -0000',
'_hpx1=BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJWE2MDVmYmUyZjBkODlmNGFhYmM5MjM5OGEwNjU2NzI5BjsAVEkiCWhvc3QGOwBGIhJhcGkuNTAwcHguY29t--aa2897a2b8ee32b650e0d830d51882e5ac8208cb; domain=.500px.com; path=/; HttpOnly' ],
'x-request-id': '7e13f562-2525-472c-9b80-9870905e6eea',
'x-runtime': '0.011553',
'x-rack-cache': 'invalidate, pass',
server: 'api20-ovh-bhs'
},
data: null
}