title: Twitter API authorization fails CORS preflight in browser
body: <p>I'm trying to do the <a href="https://dev.twitter.com/oauth/3-legged" rel="noreferrer">3-legged authorization</a> necessary to call the Twitter APIs in a browser. The process starts with getting a request token by POSTing a signed request to <a href="https://dev.twitter.com/oauth/reference/post/oauth/request_token" rel="noreferrer"><code>/oauth/request_token</code></a> (this is also how <a href="https://dev.twitter.com/web/sign-in/implementing" rel="noreferrer">sign in with Twitter</a> begins).</p>
  
  <p>My problem is that before the browser will POST to the Twitter API endpoint, it wants to <a href="https://en.wikipedia.org/wiki/Cross-origin_resource_sharing#Preflight_example" rel="noreferrer">preflight the request</a> with an OPTIONS method. This preflight request is always returning status 400 (Bad Request).</p>
  
  <p>Here's an example that you can cut and paste into a browser console that supports the Fetch API:</p>
  
  <pre><code>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' });
  </code></pre>
  
  <p>On Chrome, the preflight request looks like this (Firefox is similar):</p>
  
  <pre><code>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
  </code></pre>
  
  <p>And the preflight response looks like this:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Note that problem is <em>not</em> that I didn't specify a real authorization header in the example above. The value of the authorization header is not used in the preflight request.</p>
  
  <p>If I print out the components of my POST request to the console and assemble the pieces into a curl command (which doesn't preflight) then I can get a request token. But if I try to simulate the preflight request in curl, I haven't been able to get that to work:</p>
  
  <pre><code>$ 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.
  &gt; OPTIONS /oauth/request_token HTTP/1.1
  &gt; Host: api.twitter.com
  &gt; User-Agent: curl/7.47.1
  &gt; Accept: */*
  &gt; access-control-request-headers:authorization,content-type
  &gt; access-control-request-method:POST
  &gt; origin:http://example.com
  &gt; 
  &lt; HTTP/1.1 400 Bad Request
  &lt; content-length: 0
  &lt; date: Tue, 08 Mar 2016 23:06:44 GMT
  &lt; server: tsa_a
  &lt; x-connection-hash: 66174829ef6d3f5e5ec641ac080ad19c
  &lt; 
  * Connection #0 to host api.twitter.com left intact
  </code></pre>
  
  <p>What am I missing that will let me do a successful CORS preflight to <a href="https://dev.twitter.com/oauth/reference/post/oauth/request_token" rel="noreferrer">https://api.twitter.com/oauth/request_token</a>?</p>