Play configurations for HTTPS only on Heroku - heroku

I searched around and have found topics close to this (for example here and here) but I still can't seem to get this working so here goes.
I'm using play 2.6 and deploying to Heroku. I'd like to force the app to only use HTTPS. As the aforementioned post indicates this filter (with the proper Heoku settings) seems like it should solve my problem. But I can't seems to get it working. Basically if I do the simple setup I suggest below it doesn't redirect to https and if I try anything fancy I get errors.
I guess what I'm asking is how does one setup the Procfile, application.conf and Environment variables for the deployment to Heroku. As an FYI I'm using / I'd like to be able to use play's self signed certificates for my non production deployments in case that's causing problems.
===== For the Procfile ====
Normally a simple Procfile might look like:
web: target/universal/stage/bin/my-app -Dhttp.port=${PORT}
But without heroku I'd want to do something like this (see here)
play -Dhttp.port=disabled -Dhttps.port=443
Since Heroku sets up the port/Https automagically how do I merge these two? ie is there a heroku env var like ${HTTPS_PORT} that I should be using?
===== For the application.conf ====
Presumably we want something like this
play.filters.enabled += play.filters.https.RedirectHttpsFilter
play.filters.https.redirectEnabled = true
"play.filters.https.redirectEnabled = true" shouldn't be needed but I put it there just in case. But do I also need to specify play.filters.https.port? (see here). Something like this:
play.filters.enabled += play.filters.https.RedirectHttpsFilter
play.filters.https.redirectEnabled = true
play.filters.https.port=???
Thanks in advance.
==== Edit ===
Thanks #codefinger the answers you gave is correct. I'm going to put the details below for future reference.
As mentioned here you need to tell play to check if the request has already been secured. In this case it essentially means white listing the proxy. So the Proc file can be as simple as:
web: target/universal/stage/bin/my-app -Dhttp.port=${PORT}
But you need to enable the RedirectHttpsFilter and configure the trusted proxies. Note here I've trusted all IPs but based on your app you can restrict that (details here).
play.filters.enabled += play.filters.https.RedirectHttpsFilter
play.http.forwarded.trustedProxies=["0.0.0.0/0", "::/0"]

I think you'll need to enable the play.core.server.common.ForwardedHeaderHandler, which will detect the X-Forwarded-Proto header that Heroku sets.
TLS termination is handled by the Heroku router, which means all request are in plain HTTP when they reach your app. The only way for your app to tell if they are HTTP(S) is which this header.

Related

look for assistance with the url rewrite module in IIS

I'm trying to set up a reverse proxy for single sign on to an application. the URL to reach my app and the defined authentication method is "http://servername.domain/app/main?authsource=sso_rp"
My current config just sends me to the application login prompt. I've tested my authentication source and confirmed its working. My question is, does my URL rewrite config look like it should? there are no conditions or variables defined. i know I'm missing something simple but this isn't documented on the vendor end so seeking your help.

Checking a remote url depending upon config

I am a new NativeScript user and I am trying to understand how to have my app make a GET call to a remote server, depending upon environment. In Java world we pass in an environment variable, but I have not found an example (that I understand) demonstrating how my NativeScript mobile app will know which environment it is running in, and how to get values based upon that.
I am presuming that I will have a config/ with files such as
prod.conf.js and dev.conf.js - and there is where I will put in my urls and other config values.
How do I get my NativeScript (which I will eventually build into iOS) to reach those values to use in an http request upon startup. Any example to direction to documentation would be greatly appreciated.
Answer:
I finally got the problem solved by using Manoj suggestion of nativescript-dev-appconfig. For any newbie looking for help, try this:
{PROJECT_ROOT}/config - create the environment files as {env}.json. These files are just json, with name-value pairs of the values you want. In may case that is
When you do your build: tns build ios --bundle --env.config {dev | test | prod }
This will take the contents of the selected env.config file (ie -env.config dev and copy it as - {PROJECT_ROOT}/app/config.json .
To use it within your code,
import config from "../config.json";
axios.get(config.MY_URL).then(result => {...}
Unfortunately using environment based config files are not officially supported but there is a plugin hook you could try.
We also have webpack based environment variable support, read more about that in the docs.

How do I disable HTTPS in ASP.NET Core 2.1 + Kestrel?

So it appears with the advent of ASP.NET Core 2.1, Kestrel now automatically creates an HTTPS endpoint along side the HTTP one, and default project templates are setup to redirect from HTTP to HTTPS (which is easy enough to undo).
However my question is... how can I disable HTTPS entirely for my project. I've read through the docs and played with a variety of config settings for HTTPS but nothing I do seems to allow me to turn it off and just run an HTTP project.
Am I crazy or just missing something. I would expect this to be super easy to do.
In the Startup.cs, remove the middleware
app.UseHttpsRedirection();
If you are using Visual Studio 2017, then you can do the following:
Go to your project properties. (Right-click > Properties)
Click on the Debug tab.
Under Web Server Settings, deselect Enable SSL.
Save, build, and try again.
This will update the iisExpress settings in the launchSettings.json file.
In the file Properties/launchSettings.json of your project, look of the key applicationUrl. You will find something like:
...
"applicationUrl": "https://localhost:5001;http://localhost:5000",
...
Remove the https endpoint and it's done.
Edit
As noted by #Xorcist the file launchSettings.json is not published. So, the solution above will only work in a development environment. To disable https and, in general, to configure the urls you want to listen to, both in production and in development, you can also do one of the following:
Use --urls parameters of dotnet run, will have the same effect as the applicationUrl in launchSettings.json. For instance: dotnet run --urls=http://0.0.0.0:5000,https://0.0.0.0:5001. Again, remove the one you don't want to use.
The same can be achieved with the ASPNETCORE_URLS enviroment variable.
As mentioned in the answer by #Konstantin to this question, in ASP Net Core 2.1 you can also configure Kestrel endpoints in the appsettings.json (it seems this cannot be done in 2.0).
Finally, the same can also be achieved with the useUrls extension method WebHost.CreateDefaultBuilder(args).UseUrls("http://0.0.0.0:5000"). I prefer the other solution because this ones hardcodes you're application endpoints, and can't be changed without recompiling the application.
All the possible options are explained in detail in the Microsoft Docs on this.
Update (09 Dec 2020): these options are still valid for Net Core 3.1, as per Microsoft Docs, except for the appsettings one. Maybe it still works but I am not sure.
Update (19 May 2021): these options are still valid for Net 5, as per Microsoft Docs, except for the appsettings one. Maybe it still works but I am not sure.
Turns out the proper way to achieve what I wanted to do, was to specifically configure Kestrel with .UseKestrel() and simply specify a single address, like this:
WebHost.CreateDefaultBuilder(args)
.UseKestrel(options => {
if (context.Configuration[WebHostDefaults.EnvironmentKey] == Environments.Development) {
options.Listen(IPAddress.Loopback, 5080); //HTTP port
}
})
.UseStartup<Startup>();
in effect overriding the default setup, and displaying this warning when Kestel starts:
warn: Microsoft.AspNetCore.Server.Kestrel[0]
Overriding address(es) 'https://localhost:5001, http://localhost:5000'. Binding to endpoints defined in UseKestrel() instead.
Note the check for development environment; in production the default ports are different (80) and without HTTPS.
if a second address is specified it will assume that address is to be secured with the built-in developer cert, as such:
WebHost.CreateDefaultBuilder(args)
.UseKestrel(options => {
options.Listen(IPAddress.Loopback, 5080); //HTTP port
options.Listen(IPAddress.Loopback, 5443); //HTTPS port
})
.UseStartup<Startup>();
you may of course specifically secure your SSL address as described here:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-2.1&tabs=aspnetcore2x
which is necessary for production setups.
In the Program.cs, Add UseUrls as following:
WebHost.CreateDefaultBuilder(args)
.UseUrls("http://localhost:5000")
.UseStartup<Startup>();
And In The Startup.cs remove/comment the following:
app.UseHttpsRedirection();
The dotnet CLI now has a template for this.
dotnet new webapi --no-https
With ASPNET CORE 2.2, I simply set the web server URL to http not https and it picks it up on its own. I run it as a self hosted process.
Go to your project properties.
Click on the Debug tab.
Under Web Server Settings, set the URL to http://xxx
Try again :)
Turning off https lies in these 3 changes...
Properties/launchSettings.json
set sslPort to 0
remove the https url from the applicationUrl
Startup.cs
Remove or comment-out app.UseHttpsRedirection()
For Development & not in production:
in project properties disable Enable SSL
One more way for disabling https epecially is handy when docker is used.
Set enviroment variable in Dockerfile with only one HTTP url in value.
#https + http
ENV ASPNETCORE_URLS=http://+:5001;http://+:5000
#http only
ENV ASPNETCORE_URLS=http://+:5000
#joanlofe answer is excellent one, but there is also "stupid" way how one can reintroduce HTTPS on 5001 port. If you call Clear on your config sources (for proper layering of config sources for example) it means that one implicit source is gone -- "launchSettings.json" template. So if you rely on this file instead of "appsettings.json" (and by default you probably are) your app will enable HTTPS on port 5001.
My local k8s deployment was failing due to the existence of
"Kestrel": {
"Certificates": {
"Default": {
...
}
}
}
in an appsettings.json override, even after following the other steps here. If you're trying to strip a server of SSL (for example, if SSL is now terminated upstream), make sure to get rid of this configuration as well.
This seems pretty obvious now that I found it, but it still tripped us up for a few hours.

Camping's URL() doesn't give me "site root" as expected?

Due to circumstances beyond my control, my production Camping site appears at mysite.example.com/mysite. I'm pretty sure this is a common Apache / Passenger configuration issue, and I'm not interested in how to fix it right now because the server is out of my control. Suffice to say, the controller for "/" points there and I can't change that any time soon.
Now, for a long time, this wasn't an issue, because R(MyIndexController) points to the correct place. However, I serve my site's CSS using a Rack::Static call to make $SITE_ROOT/public accessible. This means that the stylesheet is at mysite.example.com/mysite/css/style.css. Here's where the problem comes in: the Camping URL() method, when called in my layout, gives http://mysite.example.com, not http://mysite.example.com/mysite. So I can't get it to point to the /css subdirectory, because it's missing a "hop" in the middle. When I run rackup locally, everything is fine (because this file is at localhost:8080/css/style.css), but on the production server I don't know how to fix it.
My question: is there another method (maybe directly from Rack?) that I should be calling instead? I really want to avoid hardcoding it, and/or having a hack to determine whether I'm running locally (for debug) or in production, for every rendering of the layout.
ETA: OK, this gets stranger. Obviously I've abstracted out some of the actual details above, part of which I think I "over-scrubbed". The "top level" URL is actually more akin to /mysite/rest (the developer-centric HTML presentation of our RESTful interface), as opposed to /mysite/management (accounts) or /mysite/ui (JQuery'd / "nice" UI). These are set up in our config.ru, via run Rack::URLMap.new(Hash['/rest' => RestModule, '/ui' => PrettyInterfaceModule, '/management' => UserManagerModule], etc.
So in answer to the comment below, R(Index), from a view in the RestModule, actually returns /mysite/rest/. As an example, I have a "home" link in the layout, which looks like a :href=>R(Index), and generates code that looks like <a href="/mysite/rest/">. The server is configured to serve files from ./public directly at the "site root", so ./public/css/style.css actually does apppear at http://mysite.example.com/mysite/css/style.css, as noted previously. It's that link that I'm having trouble automatically generating, and it's because of the Rack::URLMap that I thought I may have to rely on a native Rack method (not a Camping abstraction) to locate this resource.
So in this case, URL() actually returns http://mysite.example.com/mysite/rest/?
What about something like this?
URL().merge('../css/style.css')
This is an old question so I assume that you did already find a workaround but the new passenger + apache (or ngnix) behaves correctly for camping as far as I could replicate. Your app would be on the Documents root and all the includes in the /public folder so /public/css should be routed correctly regardless of you using a sub folder /mysite or not as passenger doesn't make a difference (again) as far as I can replicate. Therefore this should be easily solvable with passenger 3 + Apache or ngnix.

mod_rewrite and server environment variables

The setup I have is as follows:
I have one Apache server acting as a URL rewriting engine (SERVER1).
I have a second server (Apache too) which runs a web application (SERVER2). First tries to authenticate users. Part of the authentication protocol involves a lot of redirection between that application server and the authentication server.
My problem is that once the authencation is successfull, the authentication server needs to redirect the user back to the application server, which is only visible from SERVER1. Effectively, SERVER2 needs to be able to reconstruct a URL based on SERVER1's parameters.
Most of the environement variable are helpful i.e. I know the host name, script name, page called etcc but I can 't figure out wether the call was made through HTTP or HTTPS: that information is wiped in the rewrite process by SERVER1...
Anybody knows if/how I can get that information through environement variables? I am limited in that I can't use query string parameters...
Thanks all !
This may sound strange, but I have found part of the answer to my question.
The rewrite engine (at least in Apache 2, I haven't looked anywhere else) allows for writting extra request header.
The rule should look something like that.
RewriteRule .* -
[E=INFO_PATH_INFO:%{PATH_INFO},NE]
Put simple, it creates a new header called INFO_PATH_INFO and sets the value to PATH_INFO.
( For more info check out http://www.askapache.com/htaccess/crazy-advanced-mod_rewrite-tutorial.html )
Then it can be retrieved in any languages.
For info I am using Oracle's OWA which adds an extra layer of complication due to the fact that the default environment variables are limited to a few and additional variables need to be specified in thr dads.conf
Hope this will help anyone !

Resources