Cors fails even though set up to be permissive - http

I'm running GenHTTP server that is setup to to have CORS permissive (so allow all):
var inline = Inline.Create();
inline.Add(CorsPolicy.Permissive());
For some reason the request still fails by CORS. For context http://localhost:55409 is the server and http://localhost:55309 is the client.
Options (preflight):
Request URL: http://localhost:55409/api/v1//metadata
Request Method: OPTIONS
Status Code: 204 No Content
Remote Address: [::1]:55409
Referrer Policy: strict-origin-when-cross-origin
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Origin: http://localhost:55309
Access-Control-Expose-Headers: *
Access-Control-Max-Age: 86400
Connection: Keep-Alive
Content-Length: 0
Date: Mon, 13 Jun 2022 13:05:34 GMT
Server: GenHTTP/6.3.4.0
Vary: Origin
This returns 204 OK.
Get:
Request URL: http://localhost:55409/api/v1//metadata
Referrer Policy: strict-origin-when-cross-origin
Provisional headers are shown
Learn more
Accept: application/json, text/plain, */*
Authorization: Bearer <token>
Referer: http://localhost:55309/
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36
Returns CORS error
This also feels weird as similar requests without Authorization header return 200 OK. The options seem to be correct in that it allows everything. Why does it fail then?
Also note that this works with the other server (more proper server running .Net Web Api), so client is not to blame. I think I'm missing some crucial server setup

Turns out I needed to specifically configure it to allow Authorization header, as if * does not include it?
inline.Add(new CorsPolicyBuilder().Default(new OriginPolicy(null, new List<string>() { "authorization" }, null, AllowCredentials: true, 86400u)));
This is the answer, but I'll mark the other answer whoever can explain why * does not include Authorization as OPTIONS has returned this
Access-Control-Allow-Headers: *
so I assume that should allow Authorization header as well

Related

416 Requested Range Not Satisfiable when range is wider than content

I get an Error 416 Range Not Satisfiable response when I make an http request with a byte-range of 0-65536. The byte length of the file requested is only 3356.
Reading the spec on byte-range, it sounds like requesting a range that extends beyond the length of the file is okay, and in this case I would expect the entire file to be fetched. https://httpwg.org/specs/rfc9110.html#byte.ranges
A client can limit the number of bytes requested without knowing the size of the selected representation. If the last-pos value is absent, or if the value is greater than or equal to the current length of the representation data, the byte range is interpreted as the remainder of the representation (i.e., the server replaces the value of last-pos with a value that is one less than the current length of the selected representation).
Am I misreading the spec or is this request truly unsatisfiable? I prefer if my client does not need to know the size of the file before making the request; they could vary widely in size. The request is successful if I limit the byte-range to <= the length of the file.
The file requested is a cloud-optimized-geotiff. It is being served by a vite dev server. And the request is made using OpenLayers and geotiff.js.
Here are the DevTools details of the request and response:
General
---------
Request URL: http://localhost:3000/scenarios/1/1_parcel_fill.tif
Request Method: GET
Status Code: 416 Range Not Satisfiable
Remote Address: [::1]:3000
Referrer Policy: strict-origin-when-cross-origin
Response Headers
--------------------
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 0
Content-Range: bytes */3356
Date: Wed, 21 Sep 2022 21:38:19 GMT
Keep-Alive: timeout=5
Request Headers
-------------------
Accept: */*
Accept-Encoding: identity
Accept-Language: en-US,en;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Host: localhost:3000
Pragma: no-cache
Range: bytes=0-65536
Referer: http://localhost:3000/
sec-ch-ua: "Google Chrome";v="105", "Not)A;Brand";v="8", "Chromium";v="105"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36

Blocked by CORS policy from an express server deployed on Firebase Functions even though cors defined

I deployed my express app on Firebase Functions with cors setting. However, on the browser, the below error printed on the console.
Access to fetch at 'https://....cloudfunctions.net/users/' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
On my code,
...
import * as cors from 'cors'
const app = express()
app.use(cors({ origin: true })) // Set CORS properly
app.use(helmet())
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.use('/', router)
app.use(errorHandler)
export const users = functions
.region('asia-northeast3')
.https.onRequest(app)
I cannot find what is the problem. Even the official document recommends app.use(cors({ origin: true})). How can I solve this problem?
====EDIT====
My request looks like:
GET /baggle-318109/us-central1/auth/kakao HTTP/1.1
Host: localhost:5001
Connection: keep-alive
sec-ch-ua: "Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36
Accept: */*
Origin: http://localhost:3000
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:3000/
Accept-Encoding: gzip, deflate, br
Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
If-None-Match: W/"d-vfAVvdILIkmIo67j2sc7s17+9M0"
You send a request from localhost:3000 to localhost:5001. So, basically you use different URLs (differing by port number) and that throws a CORS error, that is saying to you that
you have a different origin from the target
the target did not allow you to do so
The solution is simple: make the target allowing you to do this. Before you continue, read this: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors
You will need to have a Access-Control-Allow-Origin header in your response at localhost:5001. You could specify a wildcard of
Access-Control-Allow-Origin: *
to allow any origin to send a request. You may allow a single source, by putting the source as a value instead of *. Read more here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
Changing the response headers and adding the Access-Control-Allow-Origin is a topic by itself and can be done differently for different servers. You will need to know what server you use for your project that's triggered when you request on localhost:5001 and to look up how can you add this header there.

Micronaut's netty server http request missing headers

I'm trying to integrate custom authentication service with micronaut security and to do this I've implemented my own AuthenticationProvider and that works fine for basic auth, however I also need to take care of authentication tokens passed in the request.
To do this I'm trying to implement my own AuthenticationFetcher and in the fetchAuthentication method I'm trying to get my custom authentication header and then authenticate the request.
#Override
public Publisher<Authentication> fetchAuthentication(HttpRequest<?> request) {
if (request.getHeaders().get(authConfiguration.getTokenHeader()) != null) {
The issue I'm having is that netty's request.getHeaders() doesn't return all headers that are being sent to the webservice (I confirmed from my browsers developer console)
GET /service/all HTTP/1.1
Accept: application/json, text/plain, */*
Cookie: m=2258:Z3Vlc3Q6Z3Vlc3Q%253D
Accept-Encoding: gzip, deflate
Host: localhost:4200
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Safari/605.1.15
Accept-Language: pl-pl
Referer: http://localhost:4200/campaigns
Connection: keep-alive
X-Token: my.token.here
And here are my app settings
micronaut:
server:
netty:
maxHeaderSize: 1024
worker:
threads: 4
parent:
threads: 4
childOptions:
autoRead: true
application:
name: appName
Any feedback appreciated.
It was caused by cors config:
micronaut:
server:
cors:
enabled: true
After adding this my request header was removed in the filter chains.

CORS: No pre-flight on GET but a pre-flight on POST

I'm trying to remove the unnecessary pre-flight requests in my application. For it I've simplified some parts of request, removed custom headers etc. But got stuck on a problem - GET requests now work fine without pre-flights, but POST requests still have them.
I've followed the requirements:
Request does not set custom HTTP headers.
Content type is "text/plain; charset=utf-8".
The request method has to be one of GET, HEAD or POST. If POST, content type should be one of application/x-www-form-urlencoded, multipart/form-data, or text/plain.
Both GET and POST requests go through the single httpinvoke call.
As an example - GET request that is not prefaced by pre-flight:
URL: http://mydomain/APIEndpoint/GETRequest?Id=346089&Token=f5h345
Request Method:GET
Request Headers:
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:uk-UA,uk;q=0.8,ru;q=0.6,en-US;q=0.4,en;q=0.2
Cache-Control:no-cache
Connection:keep-alive
Content-Type:text/plain; charset=utf-8
Host: correct host
Origin:http://localhost
Pragma:no-cache
Referer: correct referer
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36
Query String Parameters:
Id=346089
Token=f5h345
And a POST request that looks very similar but is still prefaced with pre-flight:
URL: http://mydomain/APIEndpoint/GETRequest?param=TEST
Request Method:POST
Request Headers:
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:uk-UA,uk;q=0.8,ru;q=0.6,en-US;q=0.4,en;q=0.2
Cache-Control:no-cache
Connection:keep-alive
Content-Length:11
Content-Type:text/plain; charset=UTF-8
Host:
Origin:http://localhost
Pragma:no-cache
Referer:
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36
Query String Parameters:
param:TEST
Request Payload
{MyData: {}}
Any advice would be appreciated! Thanks!
==== Update ===
As requested, posting the pre-flight request for the POST request:
URL: http://mydomain/APIEndpoint/GETRequest?param=TEST
Request Method:OPTIONS
Status Code:200 OK
Response Header
Access-Control-Allow-Origin:*
Cache-Control:no-cache
Content-Length:0
Date:Wed, 09 Aug 2017 08:02:16 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/8.5
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
Request Headers
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:uk-UA,uk;q=0.8,ru;q=0.6,en-US;q=0.4,en;q=0.2
Access-Control-Request-Method:POST
Cache-Control:no-cache
Connection:keep-alive
Host:correct host
Origin:http://localhost
Pragma:no-cache
Referer: correct referer
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36
Query String Parameters
param:TEST
It's a legacy code which uses the httpinvoke library. Code snippet that actually does the call:
_converters: {
'text json': function (input, reviver) {},
'json text': JSON.stringify
};
headers = {
'Content-Type': 'text/plain; charset=utf-8'
};
data = {params: "test"};
httpinvoke(url, method.toUpperCase(), {
corsExposedHeaders: ['Content-Type'],
headers: headers,
input: data,
converters: _converters,
inputType: 'json',
outputType: 'json',
timeout: self._getMessageTimeout()
}).then(function (res) {}, function (error) {});
This could happen if there are event listeners registered on the XMLHttpRequestUpload object (that forces a preflight; see the note on the use-CORS-preflight flag in https://xhr.spec.whatwg.org/, and a related note in https://fetch.spec.whatwg.org/ and the updated documentation on CORS preflight requests in the MDN CORS article).
Does httpinvoke do that?
As #Anne mentioned the reason that POST were sending pre-flight requests despite the requests themselves conforming to the rules of "simple requests" (and thus not needing a pre-flight) was in the XMLHttpRequestUpload event listeners.
XMLHttpRequestUpload itself might not be mentioned in the code, but you can always find it in xhr.upload variable. This was the case for http-invoke library.
So totally innocent looking code like:
xhr.upload.onprogress = onuploadprogress;
actually causes mandatory pre-flight requests.
Thanks to all who helped solve this problem.

SignalR + Node WebKit/Node fails to connect over websockets when authenticated

This is a node webkit application that manages a bunch of webkit windows. Each webkit window uses signalR to connect to a MVC/webApi/signalR stack with no problems. Each window connects to 1-3 hubs over websockets. Everything works well.
My client wants to use SignalR inside the base node application that manages all the other windows. This is where things are getting 'interesting'...
So although the node app is running in a webkit environment it is served from the file system (header:origin=file://)
So i have started up signalR like (no JSONP as i'm targeting websockets)
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration();
map.RunSignalR(hubConfiguration);
});
So when i connect in the node app before the user logs into one of the windows spawned from Node, signalR connects over websockets fine, and i don't get any errors when they login(i.e. user has changed identity).
var connection = window.$.hubConnection("http://localhost");
connection.logging = true;
connection.start()
.done(function () { console.log('Now connected, connection ID=' + connection.id); })
.fail(function () { console.log('Could not connect'); });
the issue is i don't have the identity in the HubCallerConext serverside.
So if the user logs in first, then the node application has the cookies created in the other spawned window and this is where things get weird. SignalR fails to connect over websockets with the following error (from fiddler)
Unrecognized user identity. The user identity cannot change during an active SignalR connection.
Here is the negotiate call and then the failing call to connect (upgrade) over websockets.
I have a fiddler rule replacing Origin:file:// with localhost. just in case this was effecting it.
GET http://localhost/signalr/negotiate?clientProtocol=1.4&connectionToken=qs09pHGxr6x5fff1GJ%2FChWUnpSLX5ljV8FuS3h06P%2FhpS55cjNvh2uFHHTXukDI%2BK%2BcgsC6%2BWVJHba4xrkt6IVc2KwGIfm4eeyHrigNFRotjBYKb&connectionData=%5B%7B%22name%22%3A%22windowmanagementhub%22%7D%5D&_=1429572950768 HTTP/1.1
Host: localhost
Connection: keep-alive
Accept: text/plain, */*; q=0.01
X-DevTools-Emulate-Network-Conditions-Client-Id: 2E81759B-036D-4E92-ADF4-865AFBF59D2
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-us;q=0.8,en;q=0.6
Cookie: ASP.NET_SessionId=opyggkqxnudnuag5mtxy40ai; __APPLICATION_LANGUAGE=en-GB; __RequestVerificationToken=eoB...GHjTo1; .ASPXAUTH=6909...82ED0; WindowsAuthCookie.LoginName=userName
Origin: http://localhost
and response
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
Expires: -1
Server: Microsoft-IIS/8.5
Access-Control-Allow-Origin: http://localhost
Access-Control-Allow-Credentials: true
X-Content-Type-Options: nosniff
Date: Mon, 20 Apr 2015 23:46:49 GMT
177
{"Url":"/signalr","ConnectionToken":"LwJz6Ev3+9C/NbKBqHkrI8KwYaz53qiBbzDJVlcse1qRXU3loCqOI68kUb4kpyk8gdQlkKRJ0wBrpb+VVtUMFtrtSQOEhGQE9ZNaMDBajyK2/Evz","ConnectionId":"68e7751b-aaee-4ed7-aa36-a2d1ab25107f","KeepAliveTimeout":20.0,"DisconnectTimeout":30.0,"ConnectionTimeout":110.0,"TryWebSockets":true,"ProtocolVersion":"1.4","TransportConnectTimeout":5.0,"LongPollDelay":0.0}
0
then the following connect headers, which is the request that gets the 403
GET http://localhost/signalr/connect?transport=webSockets&clientProtocol=1.4&connectionToken=LwJz6Ev3%2B9C%2FNbKBqHkrI8KwYaz53qiBbzDJVlcse1qRXU3loCqOI68kUb4kpyk8gdQlkKRJ0wBrpb%2BVVtUMFtrtSQOEhGQE9ZNaMDBajyK2%2FEvz&connectionData=%5B%7B%22name%22%3A%22windowmanagementhub%22%7D%5D&tid=0 HTTP/1.1
Host: localhost
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: http://localhost
Sec-WebSocket-Version: 13
User-Agent:
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-us;q=0.8,en;q=0.6
Sec-WebSocket-Key: HqfgeBw4svkTTpBK2CfaJA==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
and the 403 response
HTTP/1.1 403 Forbidden
Cache-Control: no-cache
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: text/html
Expires: -1
Server: Microsoft-IIS/8.5
Access-Control-Allow-Origin: http://localhost
Access-Control-Allow-Credentials: true
X-Content-Type-Options: nosniff
Date: Mon, 20 Apr 2015 23:46:49 GMT
61
Unrecognized user identity. The user identity cannot change during an active SignalR connection.
0
Here is the javascript error in the console (from jquery.signalR 2.1.2, different connection ids, tokens)
WebSocket connection to
'ws://localhost/signalr/connect?transport=webSockets&clientProtocol=1.4&connectionToken=xzGshRPvF1XvGnq2S2nDmGZ3TISMGEt01Au0z9J%2FAfMa2OtQUMW5XX5HgW0I4n2MK5UfGfpJ4%2Fl7OkiRpQlSIFrDkfy25WHScwpkubBsn5403%2Ba3&connectionData=%5B%7B%22name%22%3A%22windowmanagementhub%22%7D%2C%7B%22name%22%3A%22browserloghub%22%7D%5D&tid=1'
failed: Error during WebSocket handshake: Unexpected response code: 403
SignalR will then (correctly) fall back to SSE and connect successfully. I can see the Identity of the user serverside.
I would really like to understand why i can't connect over websockets when the user is authenticated. If i delay ALL windows from connecting to the server via signalR until the user is authenticated then i also see the same behavior.
any help or clues would be greatly appreciated.

Resources