Twitter API 授权在浏览器中未通过 CORS 预检

Posted

技术标签:

【中文标题】Twitter API 授权在浏览器中未通过 CORS 预检【英文标题】:Twitter API authorization fails CORS preflight in browser 【发布时间】:2016-06-23 03:21:57 【问题描述】:

我正在尝试执行3-legged authorization 在浏览器中调用 Twitter API 所必需的操作。该过程首先通过向/oauth/request_token 发布签名请求来获取请求令牌(这也是sign in with Twitter 的开始方式)。

我的问题是,在浏览器 POST 到 Twitter API 端点之前,它想使用 OPTIONS 方法preflight the request。此预检请求始终返回状态 400(错误请求)。

这是一个示例,您可以将其剪切并粘贴到支持 Fetch API 的浏览器控制台中:

fetch('https://api.twitter.com/oauth/request_token',  method: 'POST', mode: 'cors', headers: new Headers( authorization: 'xxx' ), body: 'oauth_callback=http%3A%2F%2Flocalhost%2F' );

在 Chrome 上,预检请求如下所示(Firefox 类似):

OPTIONS /oauth/request_token HTTP/1.1
accept:*/*
accept-encoding:gzip, deflate, sdch
accept-language:en-US,en;q=0.8
access-control-request-headers:authorization, content-type
access-control-request-method:POST
cache-control:no-cache
origin:null
pragma:no-cache
user-agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/48.0.2564.116 Safari/537.36

预检响应如下所示:

HTTP/1.1 400 Bad Request
content-length: 0
date: Tue, 08 Mar 2016 22:21:37 GMT
server: tsa_a
x-connection-hash: 529e3d8338caeb980077637d86db5df1

请注意,问题是 不是,我没有在上面的示例中指定真正的授权标头。预检请求中未使用授权标头的值。

如果我将我的 POST 请求的组件打印到控制台并将这些部分组合成一个 curl 命令(不预检),那么我可以获得一个请求令牌。但是如果我尝试在 curl 中模拟预检请求,我就无法让它工作:

$ curl -v -X OPTIONS -H "access-control-request-headers:authorization,content-type" -H "access-control-request-method:POST" -H "origin:http://example.com" https://api.twitter.com/oauth/request_token
*   Trying 199.59.148.20...
* Connected to api.twitter.com (199.59.148.20) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /opt/local/share/curl/curl-ca-bundle.crt
  CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
*    subject: C=US; ST=CA; L=San Francisco; O=Twitter, Inc.; OU=Twitter Security; CN=api.twitter.com
*    start date: Aug 11 00:00:00 2015 GMT
*    expire date: Aug 15 12:00:00 2016 GMT
*    subjectAltName: api.twitter.com matched
*    issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert SHA2 High Assurance Server CA
*    SSL certificate verify ok.
> OPTIONS /oauth/request_token HTTP/1.1
> Host: api.twitter.com
> User-Agent: curl/7.47.1
> Accept: */*
> access-control-request-headers:authorization,content-type
> access-control-request-method:POST
> origin:http://example.com
> 
< HTTP/1.1 400 Bad Request
< content-length: 0
< date: Tue, 08 Mar 2016 23:06:44 GMT
< server: tsa_a
< x-connection-hash: 66174829ef6d3f5e5ec641ac080ad19c
< 
* Connection #0 to host api.twitter.com left intact

我错过了什么可以让我成功地对 https://api.twitter.com/oauth/request_token 进行 CORS 预检?

【问题讨论】:

【参考方案1】:

我最近遇到了这个问题。我不想花很多时间创建节点服务器,所以我使用了 Netlify 的无服务器功能。它超级简单直接 + 免费。

我关注了这个博客,它非常适合我:https://www.digitalocean.com/community/tutorials/nodejs-solve-cors-once-and-for-all-netlify-dev

【讨论】:

【参考方案2】:

检查此解决方法:https://***.com/a/43881141

如果您不控制服务器,您的前端 javascript 代码是 发送请求,以及来自该响应的问题 服务器只是缺少必要的 Access-Control-Allow-Origin 标头,你仍然可以让事情正常工作——通过发出请求 CORS 代理。

简而言之,为请求添加前缀,以便完整的 URI 如下所示:

https://cors-anywhere.herokuapp.com/https://api.twitter.com/oauth/request_token

很遗憾,您将无法以这种方式使用大多数 Twitter 库,但您可以继续使用带有 cors-anywhere 前缀的 fetch。

编辑:提到的 cors-anywhere 网络服务不再永久可用,而是可以临时“激活”以供开发使用。

【讨论】:

【参考方案3】:

一种解决方法是为其创建一个 NodeJS 服务器并调用 Node API 从前端请求 Twitter API。

【讨论】:

如果您想使用 Twitter 流 API,那么您还必须设置一个 Web Socket 服务器,将所有推文推送到该套接字。然后你必须在你的前端构建一个 WS 客户端。这是一个很大的解决方法。【参考方案4】:

一种解决方法,它是一个 long 的解决方法是构建一个您使用节点或其他东西运行的代理服务器,我已经这样做了几次,这是一个很好的入门 repo对于遇到此问题的人。它具有特定于 React 的缺点,但您始终可以删除 react ui 并使用您需要的任何内容进行设置:hcra twitter build。

它来自 Mars Hall 的 Create React App/Node Express 样板

您需要克隆它并运行git fetch,然后签出twitter-req 分支。

【讨论】:

【参考方案5】:

因此,令人不满意的分辨率似乎是Twitter API does not support CORS。这让我有点吃惊,因为这意味着 API 不能从浏览器中使用。

该政策决定可能与他们的 OAuth 实施有关,即vulnerable to anyone with access to the calling platform。早在 2010 年也许还可以,但大多数其他主要的互联网玩家都知道how to do client-based authorization。

【讨论】:

2018 年仍然存在同样的问题。 2019 年仍然在这里 它的 2020 年,它仍然在这里 它的 2021 年,它仍然在这里 :( 2022 仍然在这里

以上是关于Twitter API 授权在浏览器中未通过 CORS 预检的主要内容,如果未能解决你的问题,请参考以下文章

在 Asp.Net Core 中使用 Swagger 在请求中未发送授权承载令牌

Twitter API 身份验证与授权

使用 PHP Laravel 使用 Twitter API 获取授权用户详细信息

Google OAuth Java 客户端和 Twitter API

使用 Cordova 和 Angularjs 登录 Twitter:401 未经授权的错误

twitter api 未正确验证