title: Preflight OPTIONS request returns 403/forbidden and different headers in browser
body: <p>I am currently developing a hybrid app which is also supposed to work in regular web-browsers via the official company domain later on. The backend provides a RESTful API, which support all kind of things: Getting entries, getting users, etc. The source of the request is, at least for testing and the app, not the domain itself but localhost.</p>
  
  <p>What causes issues right now is posting using <code>POST</code>, <code>Content-Type: application/json</code> and a JSON body. When run in the browser for testing, Chrome performs a preflight OPTIONS request. I understand why, no issue with this. Unfortunately, the request always turns out to have a status of 403 - which, I think, das not correspond with the HTTP status but is more of an interpretation of chrome based on the response itself. Chrome also says that the Access-Control-Allow-Origin header is missing. Here are some facts that I could evaluate:</p>
  
  <ul>
  <li>The response in chrome does indeed not contain this and some other headers. Which makes absolutely no sense, because:</li>
  <li>The same OPTIONS request works fine with Postman (HTTP 200)</li>
  <li>The behavior of Chrome is identical in at least Firefox</li>
  <li>The response I get from Postman contains all the necessary headers:</li>
  </ul>
  
  <p>The Postman-headers that come back from the OPTIONS request:</p>
  
  <pre><code>Access-Control-Allow-Origin: *
  Access-Control-Allow-Headers: X-Auth-Token, Origin, X-Requested-With, Content-Type, Accept, Authorization
  Access-Control-Allow-Methods: POST, PATCH, GET, PUT, OPTIONS, DELETE
  </code></pre>
  
  <p>Can someone help on what causes the preflight request in the browser to fail? Why does the OPTIONS response not contain the same headers in browsers and Postman? Let me know if you need further information! I didn't include code since the OPTIONS request is started by the browser and not by me anyway.</p>
  
  <p>Thanks a lot in advance and best regards.</p>
  
  <hr>
  
  <p>EDIT: Following are the complete requests from Chrome and Postman:</p>
  
  <p><strong>Chrome:</strong></p>
  
  <pre><code>General:
  Request URL: [HIDDEN]/api2/entries/57734/comments
  Request Method: OPTIONS
  Status Code: 403 
  Remote Address: [HIDDEN]
  Referrer Policy: no-referrer-when-downgrade
  
  Response:
  Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
  Cache-Control: no-cache, no-store, max-age=0, must-revalidate
  Connection: keep-alive
  Content-Length: 20
  Date: Tue, 24 Apr 2018 09:18:58 GMT
  Expires: 0
  Pragma: no-cache
  Server: nginx/1.8.0
  X-Application-Context: application:production
  X-Content-Type-Options: nosniff
  X-Frame-Options: DENY
  X-XSS-Protection: 1; mode=block
  
  Request:
  Accept: */*
  Accept-Encoding: gzip, deflate, br
  Accept-Language: de-DE,de;q=0.9,en-DE;q=0.8,en;q=0.7,en-US;q=0.6
  Access-Control-Request-Headers: content-type
  Access-Control-Request-Method: POST
  Cache-Control: no-cache
  Connection: keep-alive
  Host: [HIDDEN]
  Origin: http://localhost:3000
  Pragma: no-cache
  User-Agent: Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Mobile Safari/537.36
  </code></pre>
  
  <p><strong>Postman Headers:</strong></p>
  
  <pre><code>Access-Control-Allow-Headers: X-Auth-Token, Origin, X-Requested-With, Content-Type, Accept, Authorization
  Access-Control-Allow-Methods: POST, PATCH, GET, PUT, OPTIONS, DELETE
  Access-Control-Allow-Origin: *
  Access-Control-Expose-Headers: X-Auth-Token
  Access-Control-Max-Age: 1209600
  Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
  Cache-Control: no-cache, no-store, max-age=0, must-revalidate
  Connection: keep-alive
  Content-Length: 0
  Date: Tue, 24 Apr 2018 09:24:04 GMT
  Expires: 0
  Pragma: no-cache
  Server: nginx/1.8.0
  Strict-Transport-Security: max-age=31536000
  X-Application-Context: application:production
  X-Content-Type-Options: nosniff
  X-Frame-Options: DENY
  X-XSS-Protection: 1; mode=block
  </code></pre>