Cookies are not included when using withCredentials in XMLHttpRequest - javascript

Here is my scenario:
I am making an ajax request from foo.com to api.bar.com. In the response, it sets some cookies using Set-Cookie header. The domain on the set-cookie header is .bar.com. I am using all steps listed here How to make XMLHttpRequest cross-domain withCredentials, HTTP Authorization (CORS)?
I am able to see and verify (using Chrome extension EditThisCookie) that cookies are being set properly for domain .bar.com.
According to my understanding, when I make an ajax request (using withCredential:true) to cdn.bar.com, , it should include the cookies that were set earlier for domain .bar.com.
These cookies do not get included in the request, I can see it in fiddler. What am I missing here?
EDIT
Cookies DO get included in the request header If I make a request to cdn.bar.com from an origin app.bar.com. The problem only appears when it's called from a different origin foo.com.

The issue was with the SameSite restriction of the cookie. If I change the it from lax to No Restriction then it works fine.

Related

Intune API - CORS not enabled when uploading file to azure via link from creating mobileAppContentFile

I called https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/<id>/<LOBType>/contentVersions/<content_version_id>/files, and received the azureStorageUri from it, but when I try to upload something into it (splitting the file into chunks), I always get 403 CORS not enabled.
I add $comp=block&blockid=<base64 block id> to the received uri.
My header is:
'x-ms-block-type': 'BlockBlob'
The exact error I receive is:
<Error>
<Code>CorsPreflightFailure</Code>
<Message>CORS not enabled or no matching rule found for this request.
RequestId:ce3ea3a7-f01e-0068-24b5-2c0795000000
Time:2018-08-05T12:10:00.6698414Z</Message>
<MessageDetails>No CORS rules matches this request</MessageDetails>
</Error>
Seeing as I always get the CORS issue, I tried enabling it by following this page, but, when making the request, again I receive the same CORS error.
I'm running it in my browser, if it's any help.
I'm kinda stuck and don't know how to proceed now. I'd be happy for any help. Thanks! :)
Edit: When I make the same request via Postman, it works just fine.
I'm kinda stuck and don't know how to proceed now
If you want to send a cross-origin request successfully, the request must match the CORS configuration including the request origin, headers & response headers. By default, CORS is disabled for each service. You could add the CORS setting for storage service. We could get more information about CORS from this article.
Note: CORS is not supported for Premium Storage accounts.
We could set it from Azure portal.
You can also use the wildcard character '*' to allow all origin domains to make requests via CORS.

Dot prefix on cookie domain preventing CORS request

When I send a response from my server after authentication, I'm setting an authentication token cookie in the client's browser using this header:
Set-Cookie:mysite_auth=encodedJwtHere.JustPretend; SameSite=lax; domain=subdomain.mydomain.com; HTTPOnly; Max-Age=600; Secure; path=/
However, when I open EditThisCookie in Chrome, I can see that the domain is being set to .subdomain.mydomain.com automatically.
From what I thought I understood, this shouldn't be an issue. When I request https://subdomain.mydomain.com in the browser, the cookie is being sent.
My issue happens when I try to make a CORS request. I'm developing a javascript app and serving it on localhost. When I make an AJAX call to https://subdomain.mydomain.com, the cookie is not sent.
I have all of the proper headers set on the response:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Content-Type, *
Access-Control-Allow-Origin:*
I have the {withCredentials:true} config on my request.
If I open https://subdomain.mydomain.com in the browser, then with EditThisCookie, I remove the prefix dot, I.E. I change .subdomain.mydomain.com to subdomain.mydomain.com, suddenly my AJAX calls from localhost work. The cookie is sent with the request.
So my question is, first of all, why is the cookie not being sent when there is a prefix dot, and is there a way to resolve this issue without manually editing the domain every time my cookie is refreshed?
If you're sending credentials, you can't respond with Access-Control-Allow-Origin:* - you must respond with a value that EXACTLY mirrors the Origin request header, e.g. Access-Control-Allow-Origin: {value-of-Origin-Header}.
In your case, that would presumably be Access-Control-Allow-Origin: https://subdomain.mydomain.com. Best not to hard-code it though - just mirror back Origin value.

Can you set the Host header using fetch API

I have a reverse proxy server, which redirects you to different services depending on the Host header.
However when making requests to this server using a browser, the Host is always set to the domain name in the URL. I tried:
fetch("http://foo.com", {"headers":{"Host":"bar.foo.com"}})
But it doesn't work
Host is one of the forbidden header names:
A forbidden header name is an HTTP header name that cannot be modified programmatically.
It won't work. You cannot set the forbidden Headers on making the requests through browsers.
You can get the list of forbidden headers here - https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name
Similar answers here:
Ajax request: Refused to set unsafe header
Not able to set HTTP Host header on $.ajax request

Httprequest cookie is null after REST call to different domain [duplicate]

I know this has been asked before in various forms, but I can't seem to get around the problem.
I have tried using both jQuery and the native JS API to make the Ajax requests.
My situation is the following (see attached diagram):
Browser makes HTTP request
Server responds and sets persistent Cookie
Browser makes HTTP Ajax request, Cookie is there alright
Server responds as expected, updates Cookie
Browser makes HTTPS Ajax request, Cookie is not there anymore (?!)
Server gives "default" response, since there is no Cookie (unintended behaviour)
Before anybody starts a lecture on cross-domain requests let me state a couple of things:
I know that this is a cross-domain request (different protocol), and that's why the Server sets the Access-Control-Allow-Origin header in the response (and I am using Chrome and Firefox, both of which support CORS)
What I also know, though, is that the HTTP cookie ought to be manageable over HTTPS (see here) since the host is the same
(EDIT) The cookie is properly set for the general domain (e.g. .domain.ext) and neither the HttpOnly nor the Secure flags are set
So, why, why, why doesn't the browser pass on the cookie when making the HTTPS Ajax call? Any ideas? I am about to lose my mind...
+-----------+ HTTP Request +-----------+
|Browser |+---------------->|Server |
+-----------+ +-----------+
HTTP Response
<----------------+
Set-cookie
Ajax HTTP Req.
+---------------->
Cookie (OK)
HTTP Response
<----------------+
Set-cookie (OK)
Ajax HTTPS Req.
+---------------->
No Cookie (!!!)
Ok, found the solution to the cookie problem.
See XHR specs, jQuery docs and StackOverflow.
The solution to have the cookies sent when switching protocol and/or subdomain is to set the withCredentials property to true.
E.g. (using jQuery)
$.ajax( {
/* Setup the call */
xhrFields: {
withCredentials: true
}
});
Document.cookie and Ajax Request does not share the cookie. Otherwise, ajax can't access the cookies from document.cookie or the response headers. They can only be controlled by the remote domain.
If you first get response including cookie from server by ajax, Since that you can request ajax communication with cookie to server.
For this case, you write such as below code (jQuery)
$.ajax({
xhrFields : {
withCredentials : true
}
});
See this article and demo

Restify and Angular CORS No 'Access-Control-Allow-Origin' header is present on the requested resource

I faced with that problem when implementing REST api with Restify secured with bearer token authorization type.
when I sending simple get request to API server it fails with CORS problem
405 (Method Not Allowed) angular.js:7962
OPTIONS http://api.host.com/tests No 'Access-Control-Allow-Origin' header is
present on the requested resource. Origin 'http://local.host.com' is
therefore not allowed access.
Solution described in my answer, so it's not real question for me, because I placed it when already know the answer, but hope it will save time for someone else in future.
The problem was faced because of restify has internal CORS module who manage CORS logic. in this module you could find list of allowed headers, by default it's
[
'accept',
'accept-version',
'content-type',
'request-id',
'origin',
'x-api-version',
'x-request-id'
]
As I say in the question, I use bearer token auth, so I send my request with Authorization header. It's not included in default list, and that's why my request fails.
To fix that problem we need to add this header to the list of ALLOW_HEADERS. for that in my restify configuration code I add this line:
restify.CORS.ALLOW_HEADERS.push('authorization');
Think that info could be helpfull if you faced with similar problem, because I spend a lot to find the solution.
You won't be able to access the URL http://api.host.com/tests from a file deployed at http://local.host.com due to the same-origin policy.
As the source (origin) page and the target URL are at different domains, your code is actually attempting to make a Cross-domain (CORS) request (thus the error with OPTIONS -- see the explanation below), not an ordinary GET.
In a few words, the same-origin policy enforces that browsers only allow Ajax calls to services in the same domain as the HTML page.
Example: A page in http://www.example.com/myPage.html can only directly request services that are in http://www.example.com, like http://www.example.com/testservice/etc. If the service is in other domain, the browser won't make the direct call (as you'd expect). Instead, it will try to make a CORS request.
To put it shortly, to perform a CORS request, your browser:
Will first send an OPTION request to the target URL
And then only if the server response to that OPTIONS contains the adequate headers (Access-Control-Allow-Origin is one of them) to allow the CORS request, the browse will perform the call (almost exactly the way it would if the HTML page was at the same domain).
If the expected headers don't come in the OPTIONS, the browser will give up, informing the error (that it attempted a CORS request and didn't find the necessary headers).
How to solve it?
Place the target service in the same domain of the origin page; or
Enable CORS (enable the necessary headers) on the server; or
If you don't have server-side access to the service, you could also mirror it (create a copy of it in the server you own).
JSONP is also a solution if you just want to request information (but this would require server-side access to setup as well).

Categories