Heroku SSL redirect for MEAN app - ssl

I have a MEAN app on Heroku. I want to ensure all traffic is going via HTTPS.
I have tried two npm modules
https://www.npmjs.com/package/express-sslify and
https://www.npmjs.com/package/heroku-ssl-redirect
In my app.js file I did the following
var sslRedirect = require('heroku-ssl-redirect');
var express = require('express');
var app = express();
// enable ssl redirect
app.use(sslRedirect());
this is then used in www file
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('node-rest:server');
var http = require('http');
var sslRedirect = require('heroku-ssl-redirect');
var enforce = require('express-sslify');
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
I can't seem to get the app to redirect and thus if people use the url with https it servers them a warning

You need to enforce SSL before the express.static
app.use(express.static(path.join(__dirname, 'public')));
and then it works great

Related

SignalR .Net client cannot connect with https

I am using SignalR Core 2.4.1.0.
This is an Owin project, self-hosted.
My configuration:
public void Configuration(IAppBuilder app)
{
app.Use(async (ctx, next) =>
{
Console.WriteLine($"Incoming: {ctx.Request.Path}");
await next();
});
app.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration();
GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(10);
hubConfiguration.EnableDetailedErrors = true;
app.MapSignalR(hubConfiguration);
}
I am able to connect to https://localhost:9999/signalr/hubs from a web browser fine.
I am also able to connect to SignalR when not using https. (after removing the urlacl )
I also have tried adding a middleware before the SignalR to see the incoming request.
With http the middleware shows the Request and path.
With https the middleware shows the Request from the web browser but never shows any request from the client.
The client just changes states from connecting to disconnected with not exceptions.
My client for testing is .Net console application:
var hub = new HubConnection("https://localhost:9999");
var hubProxy = hub.CreateHubProxy("MyHUB");
hub.Error += (e) =>
{
};
hub.StateChanged += (s) =>
{
Console.WriteLine(s.NewState.ToString());
};
hub.Start();
Console.ReadLine();
I've used SignalR before but this is my first time trying to implement ssl.
In summary, .Net client will connect via http but not https.
Browser can connect to the JS library over https but I haven't tried using the JS library yet.
T.I.A.

How to set callback host (not path) for .NET Core Open ID Connect?

In .NET Core, using Open ID Connect, I'm trying to debug locally behind a local Nginx instance.
Nginx and hosts file settings are used so that a custom domain e.g. https://example.com is used to access the web app running locally, rather than the usual https://localhost:<port>
The issue I have, is that the identifty provider, Okta, always calls back to https://localhost:<port>/authorization-code/callback rather than https://example.com/authorization-code/callback. Both https://localhost:<port> and https://example.com are included in allowed callback URIs in Okta.
The .NET Open ID Connect library appears to discover the callback host automatically and I can't find a setting to change it, only the path.
.AddOpenIdConnect(options =>
{
options.ClientId = Configuration["Okta:ClientId"];
options.ClientSecret = Configuration["Okta:ClientSecret"];
options.Authority = Configuration["Okta:Issuer"];
options.CallbackPath = "/authorization-code/callback";
options.ResponseType = "code";
options.SaveTokens = true;
options.UseTokenLifetime = false;
options.GetClaimsFromUserInfoEndpoint = true;
...
Is there a setting I can use to forward the host for the callback?

Set OpenID Connect CallbackPath to HTTPS

I have a .Net Core 3.1 application that is hosted in AWS behind an https load balancer. To the outside world it is an https site, but to AWS internally it runs on http behind the balancer.
Because of this the OpenID Connect middleware is redirecting to the HTTP path instead of HTTPS.
Is there anyway to force OpenId Connect to use https pathing?
.AddOpenIdConnect("oidc", options =>
{
var oauthConfig = Configuration.GetSection("OAuthConfiguration").Get<OAuthConfiguration>();
options.Authority = oauthConfig.Authority;
options.ClientId = oauthConfig.ClientId;
options.ClientSecret = oauthConfig.ClientSecret;
options.ResponseType = "code";
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.CallbackPath = "/signin-oidc";
When the authorization request is made this generates this redirect uri
"RedirectUri": "http://demo.mysite.com/signin-oidc"
I cannot hardcore a path into the CallbackPath because my application runs multitenancy and the URL is different depending upon routing.
You can force the provider to rewrite your callback url in https like this
option.Events = new OpenIdConnectEvents()
{
OnRedirectToIdentityProvider = context =>
{
var builder = new UriBuilder(context.ProtocolMessage.RedirectUri);
builder.Scheme = "https";
builder.Port = -1;
context.ProtocolMessage.RedirectUri = builder.ToString();
return Task.FromResult(0);
}
}
The redirect URI should be an HTTPS value:
Login response returned to https://web.mycompany.com/myapp?code=a0wfd78
Load balancer routes the response to http://server1/myapp?code=a0wfd78
In terms of multitenancy I would try to avoid interfering with the Open Id Connect login process and instead use the same callback path for all users. That is the standard behaviour, and using things like wildcards in redirect URIs can create security vulnerabilities.
Not sure I fully understand understand your requirements related to multitenancy, so if this doesn't work for you, please post some further details on how you want it to work.
.Net Core has events you can override, such as this one, if the redirect URI needs to be calculated at runtime:
options.Events.OnRedirectToIdentityProvider = (context) =>
{
context.ProtocolMessage.RedirectUri = <load balanced value>;
await Task.FromResult(0);
}
Solution
The answer here is to insert middleware that pretends all requests came in as HTTPS. Works for me.
ASP.NET 5 OAuth redirect URI not using HTTPS
Warning
The following doesn't work. When deployed it causes a "Correlation failed" error, presumably because the URL was tampered with.
This is the complete fix for my website. Note that I'm loading my options from config.
.AddGoogle(options =>
{
this.Configuration.Bind("OAuth2:Providers:Google", options);
options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub", "string");
options.Events.OnRedirectToAuthorizationEndpoint = MakeHttps;
})
Importantly, this event actually performs the redirect, else you'll get a 200 OK and a blank page.
private Task MakeHttps(RedirectContext<OAuthOptions> arg)
{
// When behind a load balancer the redirect URL, which is configured as CallbackPath in the appsettings.json
// is created as HTTP because the HTTPS request is terminated at the NLB and is forwarded in clear text.
// The policy of most OAuth IDPs is to disallow clear HTTP redirect URLs.
if (!arg.RedirectUri.Contains("redirect_uri=https", StringComparison.OrdinalIgnoreCase))
{
arg.RedirectUri = arg.RedirectUri.Replace("redirect_uri=http","redirect_uri=https", StringComparison.OrdinalIgnoreCase);
}
arg.HttpContext.Response.Redirect(arg.RedirectUri);
return Task.CompletedTask;
}

Running an express server on a machine

I have a machine to which I can SSH. I have installed the express and other relevant node_modules. I have written a basic server code for "Hello World".
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.sed("Hello World!");
});
app.listen(8XXX, "172.XX.XXX.XXX");
However, i get the following error.
Error: listen EADDRNOTAVAIL 172.28.120.107:5559
I have already sshed to my mahcine. Should i be giving the IP address as "127.0.0.1" in the server code.
Very new to this . Thanks

accesing a https site using firefox addon

I am using a self signed ssl certificate to set up a https site and using the request package to access the contents on this site. However the program seems to get stuck and it is not printing the contents of the site. Is there any way to overcome this issue.
Warning: This should only be used for debugging. Automatically adding an override for a wrong SSL certificate compromises the entire connection - if you do that then you can just skip using SSL in the first place. When you release this extension for other people you should use a valid certificate.
You probably want to add a certificate override manually. That's something you would use nsICertOverrideService.rememberValidityOverride() for (chrome authority required). The only problem is getting the certificate that you want to add an override for. But trying to contact the server and calling nsIRecentBadCertsService.getRecentBadCert() then should do. Something like this:
var Request = require("request").Request;
var host = "example.com";
var port = "443";
Request({
url: "https://" + host + ":" + port + "/foo",
onComplete: function(response)
{
var status = null;
try
{
status = response.status;
} catch(e) {}
if (!status)
{
// There was a connection error, probably a bad certificate
var {Cc, Ci} = require("chrome");
var badCerts = Cc["#mozilla.org/security/recentbadcerts;1"]
.getService(Ci.nsIRecentBadCertsService);
var status = badCerts.getRecentBadCert(host + ":" + port);
if (status)
{
var overrideService = Cc["#mozilla.org/security/certoverride;1"]
.getService(Ci.nsICertOverrideService);
overrideService.rememberValidityOverride(host, port, status.serverCert,
Ci.nsICertOverrideService.ERROR_UNTRUSTED, false);
// Override added, now you should re-do the request
...
}
}
}
});
Note: This code hasn't been tested, in particular I'm not sure whether detecting connection errors will really work by checking response.status (my guess is that it should throw if there was a connection error but the documentation doesn't say anything).