当用oauth签名发布数据时,Flickr API抛出“无效的API密钥(密钥具有无效格式)”

问题描述:

我似乎无法在SO甚至Google的任何地方找到这个答案 - 我有一个oauth签名的Flickr调用上传API,并遵循the docs我已经按照通常的oauth方式(但没有photo数据)签署POST操作。出于测试目的,我只能沿着titlephoto数据传递,这意味着我结束了一个包含以下网址张贴到VAR flickrURI:在这个问题当用oauth签名发布数据时,Flickr API抛出“无效的API密钥(密钥具有无效格式)”

https://api.flickr.com/services/upload/ 
? format=json 
& oauth_consumer_key=... 
& oauth_nonce=2e57b73fec6630a30588e22383cc3b25 
& oauth_signature_method=HMAC-SHA1 
& oauth_timestamp=1411933792346 
& oauth_token=... 
& title=test 
& oauth_signature=O7JPn1m06vl5Rl95Z2in32YWp7Q%3D 

(拆分为多行是为了便于阅读,由于显而易见的原因,实际的URL在?&周围没有空白)。

oauth签名本身是非常正确的,代码用于以正确的行为访问not-upload-API,所以看起来几乎不可能得到错误的签名,除了可能签名“数据不够”或者可能使用“太多数据”签名。

中的授权签名首先形成在auth查询字符串,在这种情况下:

oauth_consumer_key=... 
&oauth_nonce=60028905f65cf9d7649b3bce98f718f8 
&oauth_signature_method=HMAC-SHA1 
&oauth_timestamp=1411939726691 
&oauth_token=... 
&title=test 

,然后将其用于形成动词+地址+编码的基本字符串:

POST&https%3A%2F%2Fapi.flickr.com%2Fservices%2Fupload%2F&oauth_consumer_key%3D...%26oauth_nonce%3D60028905f65cf9d7649b3bce98f718f8%26oauth_signature_method%3DHMAC -SHA1%26oauth_timestamp%3D1411939726691%26oauth_token%3D...%26title%3Dtest

这然后使用Flickr和oauth秘密消化HMAC-SHA1:

function sign = (data, key, secret) { 
    var hmacKey = key + "&" + (secret ? secret : ''), 
     hmac = crypto.createHmac("SHA1", hmacKey); 
    hmac.update(data); 
    var digest = hmac.digest("base64"); 
    return encodeURIComponent(digest); 
} 

并且对于GET请求,这可以很好地工作。 POST请求的事情似乎不同,尽管文档没有说明哪个部分是所谓的不同,所以我将尝试使用的NodeJS request包对在什么似乎是一个正常的方式POST操作,使用:

uploadOptions = { 
    oauth_consumer_key = auth.api_key, 
    oauth_nonce = auth.oauth_nonce, 
    oauth_timestamp = auth.oauth_timestamp, 
    oauth_token = auth.access_token, 
    oauth_signature_method = "HMAC-SHA1", 
    title: title, 
    photo: <binary data buffer> 
}; 

flickrURL = formSignedURL(auth); 

request.post({ 
    url: flickrURI, 
    headers: { 
    "Authorization": 'oauth_consumer_key="...",oauth_token="...",oauth_signature_method="HMAC-SHA1",oauth_signature="...",oauth_timestamp="...",oauth_nonce="...",oauth_version="1.0"' 
    }, 
    multipart: [{ 
    'content-type': 'application/json', 
    body: JSON.stringify(signOptions) 
    }] 
},function(error, response, body) { 
    console.log("error"); 
    console.log(error); 
    console.log("body"); 
    console.log(body); 
    } 
); 

这将产生一个包含体:

<?xml version="1.0" encoding="utf-8" ?> 
<rsp stat="fail"> 
    <err code="100" msg="Invalid API Key (Key has invalid format)" /> 
</rsp> 

因为OAuth签署并没有真正给我一个选择,其中API密钥提供(只有一个),并签署工作就好了不上传API,我无法弄清楚这个错误消息是想告诉我什么。关键是绝对正确的格式,因为这是Flickr给你的格式,而且它是正确的值,因为它在上传之外工作得很好。我还确保通过“删除”权限(尽可能广泛的权限)获取该密钥的oauth标记和密钥,以便包含的访问标记和访问标记密钥应该通过“此标记是否具有写入权限”测试。

我在这里错过了什么是显而易见的事情,这阻止了上传过程?

事实证明,将数据添加为request.post多部分信息不够好,并且会使Flickr API抛出一个“无效的API密钥(密钥无效格式)”错误,而不是说出实际错误。下面request调用,具有完全相同的数据,工作原理:

var uploadOptions = ... 

var flickrURL = ...; 

var req = request.post(flickrURL, function(error, response, body) { 
    callback(error, body); 
}); 

var form = req.form(); 
uploadOptions.photo = fs.createReadStream(...); 
Object.keys(photoOptions).forEach(function(prop) { 
    form.append(prop, photoOptions[prop]); 
}); 

尽管赚不到那么多意义上的呼叫明智的(为什么会在POST尚未被我们称之为form = req.form()的时间做了什么?)这是一个请求的“正确“的方式通过电线发送POST负载,并使Flickr API处理照片上传得很好。

看起来您正在使用https://up.flickr.com/services/upload/端点,该端点使用旧的身份验证方案。

对于OAuth,它应该是https://api.flickr.com/services/upload/。确保端点包含在签名过程中。

我不认为这是记录在任何地方,但我记得有相同的问题回来。

+0

当然,至少也会是https?除此之外,更新后的URL仍然会得到无效的API密钥。我已经更新了这个问题(是的,URl用于签名,因为VERB + url + queryarg并置) – 2014-09-29 03:23:05

+0

是的,它应该是https。我刚刚编辑它。 – ikumen 2014-09-29 03:25:13