Ameen Aliu
Ameen Aliu

Reputation: 91

Which environment variable to use on Heroku for services that only listen to https

I'm setting up an https only web API service using AspNet core which is to be deployed on Heroku. The deployment is done via docker, so I have a Dockerfile configured. But I'm getting an error relating to the https port binding whenever I deploy to Heroku. I want to know if Heroku provides a special env variable for https where a service can bind to specify the https port the service should listen to.

AspNet core provides 2 environment variables ASPNETCORE_HTTPS_PORT=5001 and ASPNETCORE_URLS=https://*:5001 where one can specify the https port the service should listen to.

But since Heroku does not allow a web process to manually specify the port it should listen to, they provide a PORT env variable the web app can bind to.

I've tried using ASPNETCORE_HTTPS_PORT=$PORT and ASPNETCORE_URLS=https://*:$PORT, but I'm getting the following errors:

crit: Microsoft.AspNetCore.Server.Kestrel[0]
Unable to start Kestrel.
System.Net.Sockets.SocketException (13): Permission denied at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName) 
at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.Sockets.Socket.Bind(EndPoint localEP)
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketConnectionListener.Bind()
at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransportFactory.BindAsync(EndPoint endpoint, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.<>c__DisplayClass21_0`1.<<StartAsync>g__OnBind|0>d.MoveNext()

Upvotes: 3

Views: 844

Answers (1)

Ameen Aliu
Ameen Aliu

Reputation: 91

So I was able to resolve the issue after going through Heroku's documentation (extensively). Here are the key findings relating to this problem:

  1. Heroku uses a load balancer which proxies all its request.
  2. Heroku terminates any SSL communication from your app, so all requests are forwarded to your app over http; your clients' https requests are proxied over http.
  3. Since the requests are proxied, Heroku passes Forwarded headers for the originating request.
  4. Your app can only receive requests and should only listen to the PORT env variable.

Now that i have the in mind, I was able to configure my app correctly.

Listening on http not https: ASPNETCORE_URLS=http://*:$PORT

Using FowardedHeaders and Rewriter middlewares in AspNet core middleware pipeline:

var forwardedHeadersOptions = new ForwardedHeadersOptions {
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
};
forwardedHeadersOptions.KnownNetworks.Clear();
forwardedHeadersOptions.KnownProxies.Clear();
app.UseForwardedHeaders(forwardedHeadersOptions);

var rewriteOptions = new RewriteOptions ().AddRedirectToHttps(308);
app.UseRewriter(rewriteOptions);
...

The ForwardedHHeaders middleware maps the Forwarded headers to HttpContext.Request. And the Rewriter middleware will redirect http request scheme to https.

Upvotes: 6

Related Questions