Golang, Heroku - How to check if request is https - heroku

Documentation suggests you can check TLS on the request object, but that appears to be nil (on heroku at least).

Looking at the Heroku documentation, it appears that HTTPS is terminated upstream of your application.
Check the request's Headers for a X-Forwarded-Proto header with the value https.

Related

Spring websocket - client CORS policy error

I am using websockets to communicate between server and client. I followed this documentation to implement websocket dependecy. Now when I try to connect via example client page it produces the following error:
Access to XMLHttpRequest at '....' from origin 'null' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
I have tried adding .setAllowedOrigins("*") to WebSocketConfig but it didn't fix this. What is the solution?
As the error message says you are sending a request with credentials set to include, I guess you are sending some kind of token/access data with your request.
When doing so your server must respond with the correct origin. If you are in development try setting your localhost. For example .setAllowedOrigins("http://localhost:8080") or what ever you are using. In production you need to replace that with your deployment url.
You might find success with .setAllowedOriginsPattern("*").
See the following documentation for more stricter patterns.

What is the HTTP/1 equivalent of the HTTP/2 `:scheme` header?

I'm writing a proxy from HTTP/2 to HTTP/1 and vice-versa.
When I have an incoming HTTP/2 request, which defines :scheme, what header should I map that to for my proxied HTTP/1 request?
The closest thing I can find is https://www.rfc-editor.org/rfc/rfc7239#section-5.4
Mapping the HTTP/2 :scheme pseudo header to HTTP/1.1 X-Forwarded-Proto header would be correct.
You basically shouldn't map it.
For a start HTTP has no direct equivalent to the :scheme pseudo-header. The request was a relative path (e.g. /path/page/) rather than an absolute path (e.g. https://www.example.com/path/page/) and the Host header contained just the server name and not the scheme.
So the connection knows whether it is HTTP or HTTPS and this is exposed to webservers and the like (e.g. in the REQUEST_SCHEME variable for Apache) but at an HTTP level it doesn't know.
If acting as an intercepting proxy and taking one HTTP/2 connection, and forwarding requests to another, then you should open a HTTP or HTTPS connection for that second connection, as you see fit depending what the downstream system supports.
As sbordet points out if you want to make the downstream system aware of what the original scheme was then you can use X-Forwarded-Proto header (technically obseleted but still used) or the Forwarded header, but that's more for informational purposes rather than a direct mapping of what was in the original request. The scheme is related to the current request.
According to RFC 7540, section 8.1.2:
While HTTP/1.x used the message start-line (see [RFC7230],
Section 3.1) to convey the target URI, the method of the request, and
the status code for the response, HTTP/2 uses special pseudo-header
fields beginning with ':' character (ASCII 0x3a) for this purpose.
And:
The ":scheme" pseudo-header field includes the scheme portion of
the target URI ([RFC3986], Section 3.1).
":scheme" is not restricted to "http" and "https" schemed URIs. A
proxy or gateway can translate requests for non-HTTP schemes,
enabling the use of HTTP to interact with non-HTTP services.
So, if you're proxing HTTP, it should be "http" and if you're proxying HTTPS, it should be "https".
Reading again, I can see that I may have had the sense of the question the wrong way around (I was thinking HTTP1 client, HTTP2 server). But the above two quotes are still the relevant ones. You don't put :scheme in an HTTP1 header - it forms part of the URI that you place in the message start line.

HTTPS and HTTP CORS

My questions is simple, but I cannot find an answer and I haven't got any resources to test it myself.
Can I make HTTPS CORS request from one domain to another HTTPS domain?
Can I make HTTP CORS request from one domain to another HTTPS domain?
I know that I can do HTTP CORS request from one domain to another HTTP domain, but I don't know if there is any difference when I use HTTPS.
Yes you can do a CORS request from a HTTPS domain to another HTTPS domain.
The only difference is because HTTPS is a secure origin, you can only make call to secure origin, so not to HTTP, the browser will block it with a message like:
Mixed Content: The page at 'https://example.com/index.html' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://example2.com/endpoint'. This request has been blocked; the content must be served over HTTPS.
Warning: If you allow http requests to call your https webpage, it will be insecure because it means an attacker can force requests to your https webpage with the cookies of a victim and read the answer
Beware if you still need to support IE8/IE9 and are using XDomainRequest as it does not support cross-protocol requests. As per MDN:
The origin's security protocol must match that of the requested URL. (http to http, https to https). If these do not match, the request will error "Access is Denied".

How do I bypass the 'ports, protocols and domains must match' CORS issue whilst in development?

I have a local site running ASP.Net MVC 3 over HTTP and HTTPS through IIS Express.
The HTTP url is http://localhost:4000 and the HTTPS is https://localhost:44301.
I'm trying to hook up the Stripe payments API but it really does not like the port, protocol and domain mismatch. I've tried using CORS to tell it to trust stripe.com but it seems that it is due to the port mismatch and I cannot figure out how to tell it to ignore that.
Adding the following header does not product any difference.
Access-Control-Allow-Origin:*
When accessing my payment page via HTTP, I get the following:
Blocked a frame with origin "https://checkout.stripe.com" from
accessing a frame with origin "http://localhost:4000". The frame
requesting access has a protocol of "https", the frame being accessed
has a protocol of "http". Protocols must match.
It gets worse when using SSL as my local SSL port is not 443.
How do I tell CORS to ignore the port mismatch whilst in development?
You can disable same origin policy while in development. Load chrome with the following argument:
--disable-web-security
https://stackoverflow.com/a/6083677/287760
Didn't the error message tell you the problem? Use HTTPs.
I still get this message my live site:
Uncaught SecurityError: Blocked a frame with origin "https://checkout.stripe.com" from accessing a frame with origin "https://getaddress.io". Protocols, domains, and ports must match.
..everything still works so I wouldn't worry about it. There's not much you can do about the domains being different.

XForwardedSupport for https play! support on Heroku failing

I am deploying an app on Heroku and trying to determine whether the request coming in is secure (request.secure). This is initially returning false on heroku because nginx handles the SSL work and communicates over plain http to the app server. So to let play read the headers that let is know it's a secure request I add:
XForwardedSupport=127.0.0.1
To application.conf as recommended in the play message boards. However, then all requests (except for images) fail with no error. It seems to be something fundamental happening before it hits the play logs. Has anyone experienced this?
I don't think Play supports the way that requests are forwarded (proxied) on Heroku via the XForwardedSupport configuration parameter. That would need to be set to the address of the Heroku load balancer and there isn't a way to configure that pre-runtime. Instead, you should just look at the x-forwarded-proto request header to determine if the request to the Heorku load balancer was via http or https. Maybe something like:
Boolean secure = false;
if (request.headers.get("x-forwarded-proto") != null) {
secure = request.headers.get("x-forwarded-proto").values.contains("https");
}
System.out.println("secure = " + secure);
BTW: Heroku's cedar stack doesn't use Nginx. It uses MochiWeb, an Erlang-based web server.
thnx big time! you saved hours of struggling with heroku+play!
I can confirm that when you set this in application.conf
XForwardedSupport=all
heroku stops complaining with SIGTERM
As pointed by #Dan Carley ticket on https://play.lighthouseapp.com/projects/57987/tickets/1406-play-123-124-playmvcrouter-does-not-fully-support-proxied-ssl#ticket-1406-4
When hosting on Heroku, (as pointed by Mirko) setting XForwardedSupport=all in application.conf works.

Resources