web-dev-qa-db-ja.com

TwitterAPI認証がブラウザーでのCORSプリフライトに失敗する

ブラウザでTwitterAPIを呼び出すために必要な 本足の認証 を実行しようとしています。このプロセスは、署名されたリクエストを /oauth/request_token (これは Twitterでサインイン が始まる方法でもあります)。

私の問題は、ブラウザがTwitter APIエンドポイントにPOSTする前に、OPTIONSメソッドを使用して リクエストをプリフライト したいということです。このプリフライトリクエストは常にステータス400を返します。 (要求の形式が正しくありません)。

FetchAPIをサポートするブラウザコンソールにカットアンドペーストできる例を次に示します。

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

上記の例で実際の認証ヘッダーを指定しなかったことがnotであることに注意してください。承認ヘッダーの値は、プリフライトリクエストでは使用されません。

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プリフライトを成功させるために何が欠けていますか?

16
rhashimoto

したがって、不十分な解決策は、 Twitter APIはCORSをサポートしていません であるように見えます。これは、ブラウザからAPIを使用できないことを意味するため、私には少し驚かされます。

そのポリシーの決定は、おそらく彼らのOAuth実装、つまり 呼び出し元プラットフォームにアクセスできるすべての人に脆弱 に関連しています。2010年には問題なかったかもしれませんが、ほとんどの場合他の主要なインターネットプレーヤーは理解しています クライアントベースの認証を行う方法

33
rhashimoto

回避策の1つは、同じノードJSサーバーを作成し、フロントエンドからTwitterAPIを要求するNode APIを呼び出すことです。

1
JanviM

コメントできないので、この回避策を確認してください: https://stackoverflow.com/a/43881141

つまり、完全なURIが次のようになるように、リクエストのプレフィックスを付けます。

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

残念ながら、ほとんどのTwitterライブラリをこの方法で使用することはできませんが、cors-anywhereプレフィックスを付けてfetchを引き続き使用できます。

0
essi

回避策であり、longの方法は、ノードなどで実行するプロキシサーバーを構築することです。これを数回実行しました。さて、これはこの問題に遭遇した誰かにとって良いスターターリポジトリです。 React固有であるという欠点がありますが、いつでも反応UIを取り除いて、必要なものをセットアップすることができます: hcra Twitter build

マースホールによるCreate React App/NodeExpressボイラープレートから分岐

クローンを作成してgit fetchを実行してから、Twitter-reqブランチをチェックアウトする必要があります。

0
ContextCue