The "Authorization" header is not sent in OPTIONS call by the browser - javascript

I have a very simple HTTP call:
fetch('http://127.0.0.1:5500/v1/homes/', {
method: "GET",
mode: "cors",
credentials: "same-origin",
headers: {
Authorization: "TEST"
}})
.then(function(response) {
console.log(response);
});
But when I look into the "Networks" tab of Google Chrome DevTools, the OPTIONS request does not have the "Authorization" header in it. This causes the server to replies with 401 Unauthorized.
The browser's curl equivalent of the request:
curl 'http://127.0.0.1:5500/v1/homes/' \
-X OPTIONS -H 'Access-Control-Request-Method: GET' \
-H 'Origin: http://localhost:8100'
-H 'Referer: http://localhost:8100/'
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
-H 'Access-Control-Request-Headers: authorization'
--compressed
Am I doing something wrong in the client side or is it quite common that browsers do not send the Authorization header in OPTIONS request, and therefore, I need to change the server in a way to response to OPTIONS call without requiring Authorization header?

is it quite common that browsers do not send the Authorization header in OPTIONS request
More than common. It is required by the CORS spec which says "for a cross-origin request with preflight … make a preflight request … Exclude user credentials".
I need to change the server in a way to response to OPTIONS call without requiring Authorization header?
Yes

An Options call is requested by the client, in your case Chrome browser implicitly before the actual GET call.
From MDN
The HTTP OPTIONS method is used to describe the communication options
for the target resource. The client can specify a URL for the OPTIONS
method, or an asterisk (*) to refer to the entire server.
On the server side, you'll have to intercept this Options request and respond back with a HTTP Status code of 200 and a Allow header indicating the operations that are permitted on this resource. eg: Allow: HEAD,GET,PUT,DELETE,OPTIONS
The browser on receiving these details will then proceed with the Get call.

Related

Custom headers get added to Access-Control-Request-Headers

I am trying to add a custom header to my angular js GET request as below:
$http({
method : 'GET',
url : s,
headers : {
"partnerId" : 221,
"partnerKey" : "heeHBcntCKZwVsQo"
}
})
But the issue is the headers are getting added to Access-Control-Request-Headers as below and I am getting 403 Forbidden response:
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:50.0)
Gecko/20100101 Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/ *;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Access-Control-Request-Method: GET
Access-Control-Request-Headers: partnerid,partnerkey
Origin: http://localhost:8080
DNT: 1
Connection: keep-alive
I also tried below changes but no luck
return $http.get(s, {
headers : {
'partnerId' : 221,
'partnerKey': 'heeHBcntCKZwVsQo'
}
})
In other related answers in SO I saw that the header partnerId and partnerKey need to be enabled in server side. But I am able to add these custom headers in POSTMAN client and other POST clients and able to get the expected response. So I guess I am missing something. Can someone guide me in this. Thanks in advance
Edit: One more thing I noted is that partnerId is replaced as partnerid while passing in the request. Not sure if that makes a difference.
If you add any headers to a scripted cross-origin request other than any CORS-safelisted request-headers, it triggers browsers to first do a CORS preflight request.
There is no way to prevent users’ browsers from doing that CORS preflight (though there are ways to get around it locally in your own browser when doing testing; for example, by using Postman).
So for users to be able to use a Web app of yours that makes scripted cross-origin requests with custom headers, the server to which those cross-origin requests go needs to be CORS-aware.
The reason Postman can make such requests without causing a preflight is, Postman’s not a browser engine—it's an extension that’s not restricted by the same-origin policy, so doesn’t need CORS.
Postman can basically do whatever curl or other such tools can do, but just within a browser UI for convenience. It’s otherwise bypassing normal Web-security features built into browsers.

fetch—POST json not working [duplicate]

I got this code:
var req = new HttpRequest();
req.open("POST", "http://localhost:8031/rest/user/insert");
req.setRequestHeader("Content-type", "application/json");
req.send(json.stringify(user_map));
But, instead of sending the POST verb, when I see it in fiddler I see this:
OPTIONS http://localhost:8031/rest/user/insert HTTP/1.1
Host: localhost:8031
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://127.0.0.1:3030
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 (Dart) Safari/537.33
Access-Control-Request-Headers: origin, content-type
Accept: */*
Referer: http://127.0.0.1:3030/E:/grole/dart/Clases/Clases/web/out/clases.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: es-ES,es;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
As you can see, it is using the OPTIONS verb instead of POST?
What's going on?
The OPTIONS verb is a preflight request sent by some browsers to check the validity of cross origin requests. It pretty much checks with the server that the Origin(requester) is allowed to make the request for a specified resource. Also, depending on which headers are sent back by the server it lets the browser know which headers, methods, and resources the origin is allowed to request form the server.
The browser sends the OPTIONS request then if the server answers back with the correct headers (CORS headers) allowing the origin to make the request, you should see your POST request go through afterwards.
Note that the CORS headers must be returned on both the OPTIONS response as well as the POST response. This means your server must be able to respond to the options method on the routes you want to access across domains.
This is known as Cross-origin Resource Sharing. Mozilla has some pretty good documentation on the subject. https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS
If you have more questions let me know and I'll answer them.
One way to avoid this problem is by sending the request payload without custom headers and using formData to setup your request payload.

Unable to create session using SessionToken in okta POST /sessions API call

I was able to get the sessionToken using username and password. But, after that I want to create the session using POST call as follows in AngularJS. The angular (entire web app) is hosted on AWS S3.
var session_data = { 'sessionToken' : My_session_Token};
$http({
method: 'POST',
url: 'https://myorg.okta.com/api/v1/sessions',
data: session_data,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
}).then(function(response) {
console.log(response);
});
The error I am getting is
XMLHttpRequest cannot load https://myorg.okta.com/api/v1/sessions. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://s3.amazonaws.com' is therefore not allowed access.
I have already added the CORS Allow origin header in Okta as well as S3 bucket.
When I try doing the following through terminal
curl -v -X POST \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"sessionToken": "my_session_Token"
}' "https://myorg.okta.com/api/v1/sessions"
First time I get
{"errorCode":"E0000005","errorSummary":"Invalid session","errorLink":"E0000005","errorId":"oaefADOnPONTDidUZYyrVc5rQ","errorCauses":[]}MAC-S014568:~
second time, because of sessionToken is one time use only I get following error
{"errorCode":"E0000004","errorSummary":"Authentication failed","errorLink":"E0000004","errorId":"oaeI-KKSO-iRGSR1gmyUjBS8g","errorCauses":[]}MAC-S01
I don't think the problem is because of the CORS header (Allow origin) as I have already added the origin.
Also, I cannot use SSWS {api_TOKEN} as my application is in angular and its risky to expose the api token.
Any help will be highly appreciated
Okta doesn't support POSTing to /api/v1/sessions to set a cookie in the browser. For a simple use case, you can use the redirect flow:
window.location = 'https://myorg.okta.com/login/sessionCookieRedirect?token={sessionToken}&redirectUrl={redirectUrl}';
All the allowed methods of setting a cookie using a sessionToken are listed here: http://developer.okta.com/use_cases/authentication/session_cookie

PouchDB authentication triggering CORS preflight request

The following code (using the PouchDB Authentication plugin) fails because it triggers the browser to send a CORS preflight request, and CouchDB does not support the OPTIONS HTTP method.
var db = new PouchDB("http://localhost:5984/mydb");
db.login('username', 'password');
// assume the database URL and login info are valid
Here is the error (in Chrome). Note that this issue also occurs in Edge, but not in Firefox:
XMLHttpRequest cannot load http://localhost:5984/_session. Response for preflight has invalid HTTP status code 405
And here are the headers that Chrome is sending for the request (they are not significantly different in Firefox):
POST /_session HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 25
Accept: application/json
Origin: http://localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://localhost:8080/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,es-419;q=0.6,es;q=0.4
I have already enabled CORS via the add-cors-to-couchdb Node script. Things I have tried:
Manually adding OPTIONS as a method under [cors] in my local.ini
Passing { ajax: { content_type: "text/plain" } } as the third argument to login
So, my question is:
How can I prevent the preflight request from being triggered? Looking at the MDN documentation, it doesn't seem necessary.
If the previous is not possible, how can I set my CouchDB server up to respond to preflight requests?
Hitting this same issue. Seems Chrome has recently started being a little more aggressive about sending the OPTIONS preflight.
A partial work around was to specify a specific origin in the CORS header instead of '*',
so
curl -X PUT $HOST/_config/cors/origins -d '"localhost:8080"'
or similar.
I still am getting the preflight error, but now PouchDB successfully authenticates, so I can just ignore the error.
I think the fix is to get CouchDB to respond to OPTIONS on the _session url.
Edit, more info here
https://github.com/nolanlawson/pouchdb-authentication/issues/111
With the latest PouchDB you authenticate like so:
var remote = new PouchDB("http://user:password#localhost:4984/bucket/");

emberJS JSONAPI adapter sends OPTION instead of GET request [duplicate]

This question already has answers here:
Why am I getting an OPTIONS request instead of a GET request?
(10 answers)
Closed 6 years ago.
I am trying to make basic request to a working server (checked through google POSTMAN) in an emberJS application. But when I try it, I get http 404 error. Then I inspected the error, and saw that the original request which comes from client side came as OPTION request instead of GET request. Also, I've set two header, Accept and Content-Type to be application/json and when inspecting, inspector printed these headers:
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:accept, content-type
Access-Control-Request-Method:GET
Connection:keep-alive
Host:frontend.com
Origin:http://localhost:4200
Referer:http://localhost:4200/restaurant
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36
Now here is the adapter
//Application.js adapter:
import DS from 'ember-data';
export default DS.JSONAPIadapter.extend({
host: 'http://server.com',
namespace: 'v1',
headers: {
"Accept": "application/json",
"Content-Type": "application/json"
}
});
Is there some way to turn this OPTION off, or is there some workaround? I didn't believe ember was so buggy, because these is supposed to be one of main things that emberJS should do - send requests.
Any help is appreaciated.
This is "request preflight". While doing a cross origin request, browser first sends a preflight request by sending an OPTION request. If the OPTION request is responded successfully, the real request would be send to the server.
The "preflight" fails in such cases:
CORS is not enabled by the server
authentication / authorization problems are occured
service function is not found (404)
service function do not accept the header you will send
You may search with these keywords: preflight, cors

Categories