Javascript 如何通过jQueryAjax从使用OAuth1.0身份验证的UpworkAPI请求JSONP文件?

Javascript 如何通过jQueryAjax从使用OAuth1.0身份验证的UpworkAPI请求JSONP文件?,javascript,jquery,ajax,api,oauth,Javascript,Jquery,Ajax,Api,Oauth,我需要通过jQueryAjax从服务器请求一个JSONP文件。UpWorkAPI使用OAuth 1.0身份验证 我不熟悉Oauth,但在过去几天里一直在阅读有关它的内容,我大致了解它是如何工作的,但在这个特定场景/环境中实现它非常困难。几天来我一直在绞尽脑汁,Upwork API支持也没有多大帮助:( 我需要通过OAuth 1.0中所有必要的步骤,并获得与请求url一起传递的OAuth参数。请帮助! 以下是我迄今为止所做的工作: // My Upwork API key and secret v

我需要通过jQueryAjax从服务器请求一个JSONP文件。UpWorkAPI使用OAuth 1.0身份验证

我不熟悉Oauth,但在过去几天里一直在阅读有关它的内容,我大致了解它是如何工作的,但在这个特定场景/环境中实现它非常困难。几天来我一直在绞尽脑汁,Upwork API支持也没有多大帮助:(

我需要通过OAuth 1.0中所有必要的步骤,并获得与请求url一起传递的OAuth参数。请帮助!

以下是我迄今为止所做的工作:

// My Upwork API key and secret
var api_key = 'xxx',
    api_secret = 'xxx';


// TO-DO
// OAuth 1.0 authentication


// TO-DO
// required oauth parameters
// https://developers.upwork.com/?lang=node#authentication_required-oauth-10-parameters
var oauth_consumer_key = '',
    oauth_signature = '',
    oauth_nonce = '',
    oauth_signature_method = '',
    oauth_timestamp = '',
    oauth_token = '';


// Compose request url with required oauth parameters
var url  = "https://www.upwork.com/api/profiles/v2/search/jobs.json?q=java&callback=?";
url += "&oauth_consumer_key="+oauth_consumer_key;
url += "&oauth_signature="+oauth_signature;
url += "&oauth_nonce="+oauth_nonce;
url += "&oauth_signature_method="+oauth_signature_method;
url += "&oauth_timestamp="+oauth_timestamp;
url += "&oauth_token="+oauth_token;


// Ajax request
// https://developers.upwork.com/?lang=node#getting-started_cross-domain-requests
$.ajax({
  url: url,
  dataType: 'JSONP',
  success:function(json){
    alert("Success: "+json.server_time);
  },
  error:function(){
    alert("Error");
  },
});
代码笔:


提前感谢!

TLDR我从OAuth 1.0过程描述开始,以确保下面的代码示例和我的结论都是清晰的。 如果OAuth进程已清除,请跳到代码部分

OAuth1.0进程 我使用以下术语(它们不同于官方术语,但希望能让事情更清楚):

  • 应用程序-您的应用程序
  • 服务-从中请求数据的服务
  • 用户-允许您访问服务存储的数据的用户
准备。在服务中注册你的应用程序 您将获得用于启动Oauth进程的客户机密钥和密码

在向上工作的情况下,您可以在这里执行此操作-

步骤1.获取临时oauth令牌。 此请求由您的应用程序向服务发出。 您的应用程序将传递
客户端密钥
,以便服务知道是谁询问

该请求是使用
客户端密码签署的,该服务也拥有该密码,并且可以验证它是否确实是来自您的应用程序的请求,而不是来自窃取您的客户端密钥的其他人的请求(这就是您不应该向任何人显示您的密码的原因)

服务器返回
临时oauth令牌
+
临时oauth密钥

在Upwork的情况下,您将此请求发送给

步骤2.要求用户授予您访问权限。 您的应用程序只是将用户重定向到服务提供的特殊URL

该服务显示一个对话框,用户可以在其中为您的应用程序提供访问权限。 此特殊URL包含步骤1中的
临时令牌
,因此服务知道哪个应用程序请求访问

如果您有一个web应用程序,只需在浏览器中打开此特殊url即可。 然后,该服务使用
oauth_回调
(将用户重定向回的URL)重定向回您的应用程序。 该服务还将
oauth\u验证器
传递给
oauth\u回调
URL

如果您有一个桌面应用程序,它应该启动浏览器,该服务可以将
oauth\u校验器
显示为字符串,这样用户可以手动复制它并粘贴回您的应用程序。在这种情况下,您可以将
oauth\u calback
设置为特殊的
oob
(带外)值。 规范中没有严格描述此部分(没有重定向回),因此详细信息取决于服务。 它可能根本不受支持,或者以其他方式得到支持

对于Upwork,您将用户发送到URL{temporary token}

步骤3.获取真正的oauth访问令牌。 您的应用程序将临时令牌从步骤1和oauth验证器从步骤2发送到服务。 请求再次被签名,但这次使用的是
客户端密码
临时令牌密码
。 服务使用访问令牌+机密进行响应

在Upwork的情况下,URL是

这是获得真正的access toking并开始使用服务API的3个步骤。 规范中的示例也很好且清晰

还要注意,OAuth 1.0不能在100%客户端应用程序中安全使用。 在步骤1中,您需要使用私有的
客户机机密
,任何人都不应该知道它(因此您不能将其放入客户端代码中)。 在步骤2中,服务将把浏览器重定向回
oauth\u回调
,而您无法在客户端处理它

从技术上讲,如果您在没有回调的情况下使用场景(如桌面应用程序),则可以使用oauth客户端。在这种情况下,用户需要手动将验证器复制回您的应用程序。 这个场景也应该得到Servcie的支持(Upwork不支持它,请参见下文)

步骤4.使用服务API 现在,一旦您获得了访问令牌,就可以发出API请求来获取数据,在这里您可以发送步骤3中的
客户机密钥和
访问令牌。
请求使用
客户机密码
+
访问令牌密码
签名

该过程中最复杂的部分是请求签名,规范中详细介绍了这一部分,但最好使用库

允许您在node.js和客户端javascript中对请求进行签名。 您仍然需要从应用程序中执行oauth步骤,该库只会帮助您进行签名

代码 我从浏览器javascript测试了
步骤1
,Upwork不支持这种情况。 如果我使用ajax发送常规POST请求,它将返回“Access Control Allow Origin
错误。如果我使用
JSONP`尝试此请求,Upwork将以404错误响应

因此,
JSONP
不支持
api/auth/v1/oauth/token/request
端点

步骤1-3应该使用服务器端完成(无论如何,客户端身份验证是不安全的)

以下是令牌请求的外观(
步骤1
):

完整的代码是

请注意,Upwork具有相同的功能,但我并没有使用它来手动完成所有事情。 请求使用签名

步骤2
在浏览器中执行,在这里,您只需像“”一样打开url并获取oauth验证器。 在现实生活中
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) // no token yet
    }, function(error, response, body) {
        var data = qs.parse(body);
        console.log(data);
    });
};
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) // use the temp token
    }, function(error, response, body) {
        var data = qs.parse(body);
        console.log(data);
    });
};
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) // use the access token
    }, function(error, response, body) {
        console.log(body);
    });
};
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'
        }
    };

    // It looks like a bug on the Upwork side, the `callback` parameter is usually
    // selected randomly by jQuery, so server side should skip it from the signature
    // validation, but it doesn't, so we sign the request with `callback` parameter
    // and then remove it from data, because it this parameter is automatically added
    // by jQuery, we also set the static value for callback - 'jsoncallback`
    var data = oauth.authorize(request_data, accessToken);
    delete data.callback;

    // Ajax request
    // https://developers.upwork.com/?lang=node#getting-started_cross-domain-requests
    $.ajax({
      // url: url,
      url: request_data.url,
      dataType: 'JSONP',
      jsonpCallback: 'jsoncallback',
      // here the data will contain 'q=java' as well as all the oauth parameters
      // the request type will be GET (since this is JSONP), so all parameters will
      // be converted to the query string
      // you can check the URL in the developer console, in the list of network requests
      //data: oauth.authorize(request_data, accessToken),
      data: data,
      cache: true, // this removes the '_' parameter
      success:function(json){
        console.log(json);
      },
      error: function(error){
        console.log(error);
      },
    });
};
$ node
> oauthTest = require('./server')
> oauthTest.step1_tempToken()
> // wait for the result
{ public: 'xxxx',
  secret: 'yyyy' }
> // copy the public temp access token
> // don't exit it yet
>
> 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
> 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}