TLDR 为了确保下面的代码示例和我的结论更加清晰,我将从OAuth 1.0流程描述开始。
如果您已经理解OAuth过程,请跳到代码
部分。
OAuth 1.0流程
以下术语可能与官方术语不同,但希望能使事情更加清晰:
- App - 您的应用程序
- Service - 您请求数据的服务
- User - 提供访问其由Service存储的数据的用户
准备工作。在Service中注册您的App
您将获得用于启动Oauth过程的客户端密钥和密钥。
在Upwork的情况下,您可以在此处执行此操作 - https://www.upwork.com/services/api/apply。
步骤1.获取临时oauth令牌。
您的App向Service发出此请求。
您的App传递client key
,因此Service知道谁在请求。
请求使用client secret
进行签名,Service也有它,并且可以验证它是否实际上是来自您的App而不是从窃取您的客户端密钥的其他人(这就是为什么您不应向任何人显示您的密钥的原因)。
服务器返回temporary oauth token
+ temporary oauth secret
。
在Upwork的情况下,您将此请求发送到https://www.upwork.com/api/auth/v1/oauth/token/request
步骤2.请求用户授权访问。
您的应用程序只需将用户重定向到Service提供的特殊URL。
服务显示一个对话框,用户可以在其中为您的应用程序提供访问权限。
这个特殊的URL包括第1步中的temporary token
,因此Service知道哪个应用程序请求访问权限。
如果您有一个Web应用程序,只需在浏览器中打开此特殊的URL。
然后,Service使用oauth_callback
(要将用户重定向回的URL)重定向回您的App。
服务还将oauth_verifier
传递给oauth_callback
URL。
如果您有一个桌面应用程序,则应启动浏览器,并且Service可以将oauth_verifier
显示为字符串,以便用户可以手动复制它并粘贴回您的App。在这种情况下,您将oauth_calback
设置为特殊的oob
(out-of-band)值。
此部分(不包括重定向回)在规范中没有严格描述,因此详细信息取决于Service。
它可能根本不受支持,或以其他方式受支持。
在Upwork的情况下,您将用户发送到URL
https://www.upwork.com/services/api/auth?oauth_token={temporary token}。
第三步。获取实际的OAuth访问令牌。
您的应用程序将步骤1中的临时令牌和步骤2中的OAuth验证器发送给服务。
该请求再次签名,但这次使用客户端密钥和临时令牌密钥。
服务响应访问令牌+密钥。
在Upwork的情况下,URL为
https://www.upwork.com/api/auth/v1/oauth/token/access
这些是获取实际访问令牌并开始使用服务API的3个步骤。
规范中的示例也很好,
请查看。
还要注意,OAuth 1.0不能在100%客户端应用程序中安全使用。
在步骤1中,您需要使用私有的客户端密钥,不应为任何人所知(因此您不得将其放入客户端代码中)。
在步骤2中,服务将重定向浏览器回到oauth_callback,您无法在客户端处理它。
从技术上讲,如果您使用没有回调的方案(例如桌面应用程序),则可以在客户端使用oauth。
在这种情况下,用户将需要手动将验证器复制回您的应用程序。
服务还应支持此场景(Upwork不支持,请参见下文)。
第4步。使用服务API
现在,一旦您获得访问令牌,就可以发出API请求以获取数据,这里发送步骤3中的客户端密钥和访问令牌。
请求使用客户端密钥+访问令牌密钥进行签名。
该过程最复杂的部分是请求签名,在规范中详细介绍了它,但最好使用库来完成此操作。
oauth-1.0a允许您在node.js和客户端javascript中签署请求。
您仍然需要从应用程序执行oauth步骤,库将只帮助您签名。
代码
我从浏览器JavaScript测试了Step 1,但Upwork不支持此场景。
如果我使用ajax发送常规POST请求,则返回“Access-Control-Allow-Origin
error。如果我尝试使用
JSONP`进行此请求,Upwork会响应404错误。
因此,api/auth/v1/oauth/token/request
端点不支持JSONP
。
步骤1-3应该使用服务器端完成(客户端身份验证可能不安全)。
以下是令牌请求的示例(Step 1
):
oauthTest.step1_tempToken = function() {
var request_data = {
url: 'https://www.upwork.com/api/auth/v1/oauth/token/request',
method: 'POST',
data: {}
};
request({
url: request_data.url,
method: request_data.method,
form: oauthTest.oauth.authorize(request_data)
}, function(error, response, body) {
var data = qs.parse(body);
console.log(data);
});
};
完整代码在
这里。
请注意,Upwork有
nodejs库,但我没有使用它来手动完成所有事情。请求是使用
oauth-1.0a进行签名的。
在浏览器中执行
步骤2
,只需打开网址 'https://www.upwork.com/services/api/auth?oauth_token=xxx' 并获取oauth验证器。在现实生活中,您的应用程序将指定
oauth_callback
参数,Upwork将向您的应用程序发送oauth验证器。在此示例中,我只是手动从浏览器复制它并传递到下一步。
有了oauth验证器,您可以获取永久访问令牌(
Step 3
):
oauthTest.step3_accessToken = function(oauth_verifier) {
var request_data = {
url: 'https://www.upwork.com/api/auth/v1/oauth/token/access',
method: 'POST',
data: {
oauth_verifier: oauth_verifier
}
};
request({
url: request_data.url,
method: request_data.method,
form: oauthTest.oauth.authorize(request_data, oauthTest.tempToken)
}, function(error, response, body) {
var data = qs.parse(body);
console.log(data);
});
};
最后,您可以使用API中的第四步
(再次强调,这是服务器端代码):
oauthTest.queryAPI = function() {
var request_data = {
url: 'https://www.upwork.com/api/profiles/v2/search/jobs.json',
method: 'GET',
data: {
'q': 'java'
}
};
request({
url: request_data.url,
method: request_data.method,
qs: oauthTest.oauth.authorize(request_data, oauthTest.accessToken)
}, function(error, response, body) {
console.log(body);
});
};
可以在客户端使用API(尽管这不好,因为您需要将访问令牌和密钥放入代码中)。
解决方案有些棘手,因为文档(https://developers.upwork.com/?lang=node#getting-started_cross-domain-requests)不完整,也不完全正确。
文档中说要在请求中添加callback=?
,但是当您设置JSONP
数据类型时,jQuery会自动添加此参数。此外,参数值被设置为一些随机字符串,因此我认为此参数不应该被签名,但实际上它应该:
function queryAPI(public, secret) {
var accessToken = {
public: public,
secret: secret
}
var request_data = {
url: 'https://www.upwork.com/api/profiles/v2/search/jobs.json',
method: 'GET',
data: {
'q': 'java',
'callback': 'jsoncallback'
}
};
var data = oauth.authorize(request_data, accessToken);
delete data.callback;
$.ajax({
url: request_data.url,
dataType: 'JSONP',
jsonpCallback: 'jsoncallback',
data: data,
cache: true,
success:function(json){
console.log(json);
},
error: function(error){
console.log(error);
},
});
};
无论如何,这是不安全的。由于您需要服务器端进行Oauth,因此您也可以使用它来向API发出请求并将结果返回到客户端。
如何使用代码示例
获取nodejs-upwork-oauth文件夹的副本,执行npm install
并启动node.js控制台:
$ node
> oauthTest = require('./server')
> oauthTest.step1_tempToken()
>
{ public: 'xxxx',
secret: 'yyyy' }
>
>
>
现在在浏览器中打开
test.html
,并打开JS控制台,运行:
> step2_askUser('temp_access_token_here')
> // it will open the upwork auth page in new tab
Application authorized
jobs-alert has been authorized.
Your oauth_verifier=zzzz
You can close this window and return to your application.
> // authorize there and copy the oauth_verifier
回到Node.js控制台:
> oauthTest.step3_accessToken('oauth verifier here')
> // wait for the result
{ public: 'nnnnn',
secret: 'kkkkk' }
> oauthTest.queryAPI()
> // see the query result
然后回到浏览器:
> queryAPI('access token public', 'access token secret')
< Object {server_time: 1456301893, auth_user: Object, profile_access: "public,odesk", jobs: Array[10], paging: Object}