How to set up SSL certificate for redirecting a subdomain to localhost

Hello,

I am trying to set up a self-hosted listening app (as part of a winforms desktop application), which will eventually be installed on individual users’ machines, that listens though localhost for an OAuth response from a website.
This needs to be done through SSL, so through sslforfree.com (which uses Let’s Encrypt), my company applied for and received the SSL certificates for a subdomain on their site that is to be used specifically for forwarding to localhost. There will be an entry made in the users’ hosts file that redirects the subdomain to localhost.

I had previously gotten all of this working through use of self-signed root/server certificates that I made using makecert.exe. I bound the server certificate to the listening port (I’m using 44301) with a netsh command:
netsh http add sslcert ipport=0.0.0.0:{port} certhash={serverCertificateThumbprint} appid={{guid}}
With the self-signed certificates I did get a certificate warning error in Chrome when the OAuth response was sent back, though a successful connection was still made after clicking to proceed past that warning. However, I can’t use self-signed certificates outside of development since this will be distributed to end-users.

I received the SSL certificate files for my company’s subdomain (ca_bundle.crt, certificate.crt, and private.key). I installed both of the .crt certificates on my dev machine just like I did for the self-signed certificates, and also bound the listening port in the same way, but I can’t get it to work properly. And when I try to browse directly to https://localhost:44301 in Chrome (when the listener is running), I get the error page: ERR_CONNECTION_RESET.
What steps am I missing to get this working?

Hi,

You might want to try a "Private CA", which will allow a certificate to be issued to localhost or local addresses.

Public CAs are not allowed to issue a local certificate (e.g. 127.0.0.1 or localhost whatsoever)

It should give you an error claiming "Common Name not match" (since you are using local domains)... However, for reason that your server is responding with Connection Reset... I have no clue...

P.S. Go to serverfault might help you more.

They will issue a certificate for a public domain that happens to have an A record to 127.0.0.1, though.

Still, the plan might prove problematic. Sharing the private key and certificate with customers will probably lead to it being revoked!

1 Like

Hi @John56789

if you create a winforms desktop application, you can define, that certificate errors should be ignored. So the application can connect localhost with a self-signed certificate.

my company applied for and received the SSL certificates for a subdomain on their site that is to be used specifically for forwarding to localhost.

You can create a hosts - entry

127.0.0.1 subdomain.site

so local request don't use the webversion.

But in this case, you would need to deploy the certificate with the private key. This is not a good idea.

You’d be reasonably safe issuing certificates to one subdomain per client. For instance, Boss Construction gets a bossconstruction.yoursoftware.com cert, and you update their host file or just put 127.0.0.1 in the global DNS; your client signs something to the effect that yes, they’ll keep users from getting the key, they won’t allow anyone to install mimikatz, and so on. You could go further, to make every installation a new cert, but limiting exposure to a single company/contract is compliant with CA/B rules, as far as I know.

However, for a purely internal app, you should rely on private PKI rather than public PKI. Either generate a certificate pair at install time (and optionally install into the root store) and compare to that, or utilize the client’s existing PKI to generate a unique trusted intermediate from the organization’s root, if they have one. I’ve done a lot of ad-hoc PKI over the years, I know what a pain it is, but telling the client that they have to generate a root if they don’t already have one, push it out, protect it, and have a small API you can provide to generate intermediates is not unreasonable. (Try not to generate certs straight off the root. It’s messy.)

Thank you for the responses so far. Are you saying that an SSL cert issued for a subdomain by a public CA isn’t going to work for what I’m trying to do?

After installing the subdomain cert I can’t even manually browse to https://localhost:44301 when the listener is running, yet it works with my self-signed cert; I think that is the primary issue to tackle. Getting it working on my local machine would be the first step, then I can figure out how it will be distributed among users. Ultimately, I will need a one-size-fits-all solution that works for any client, so I can’t generate separate SSL certs for individual clients, for example.

My best guesses as to why I can’t get this working are: 1) the cert doesn’t work because that subdomain doesn’t actually exist on my machine, or 2) I installed the cert files improperly. I have also tried converting the .crt file to .cer in case the cert format wasn’t right (using the instructions here: http://www.networksolutions.com/support/what-is-the-difference-between-a-crt-and-a-cer-file/), but that didn’t make a difference in the outcome.

I know what I’m trying to do with SSL is somewhat unusual, and the main reason I need to jump through all these hoops is that the website from which I am receiving the OAuth response (QuickBooks Online), requires the redirect URL to be HTTPS, and not be localhost, for a production setup. I have successfully worked around the localhost requirement through having an entry in the hosts file, it’s just the HTTPS part I’m stuck on. This is only an issue for me because I am listening for the response through a desktop app and not through a website like most other people are doing with this integration. More information about this can be seen here, with the latest post being mine. https://help.developer.intuit.com/s/question/0D50f00004txzm8CAA/integrating-desktop-application-with-quickbooks-online

Hi,

What others trying to say is "setup a domain name (hostname)" and set the DNS value to 127.0.0.1 which would work as localhost.

Public CA are not allowed to issue certificates for "localhost", but they are allowed to issue a certificate for some public hostname pointing to 127.0.0.1

Thank you

If you use 127.0.0.1 instead of localhost you probably won’t need to worry about SSL at all.

Many browsers and OAuth providers will treat 127.0.0.1 as a secure context even when not using HTTPS, whereas localhost gets no special treatment. This is because localhost can be redirected to different machines via the HOSTS file or DNS tricks, but 127.0.0.1 cannot.

1 Like

I tried your suggestion of changing my listener to use 127.0.0.1 instead of localhost, but I’m ending up with the same results, at least in Chrome. Here’s what I tried:

  1. listening on http://127.0.0.1:44301: By itself, this address works through the listener (i.e. when I manually browse to this address while the listener is running), but it doesn’t work when the HTTPS subdomain address tries to redirect to this - I get ERR_SSL_PROTOCOL_ERROR. Probably because I tried to forward an HTTPS address to an HTTP address.
  2. listening on https://127.0.0.1:44301. This only works when I set up a self-signed certificate and bind the cert to the port in the same fashion as I did with localhost. I still get the same warning page in Chrome as I did when using localhost. NET::ERR_CERT_COMMON_NAME_INVALID

You need to convince the web application to not use HTTPS for the redirect. If it redirected to http://127.0.0.1:44301, it would work fine, and the browser would be happy to treat it as a secure context. The only way this doesn't work is if it tries to force HTTPS.

However, from the intuit forum page you linked, we can read:

For production settings, localhost is not allowed and https is required. You can add an entry in your etc/host file to define a local domain as localhost however.

So, while Patches' solution is the correct one, it's not possible to apply in this case.

By the way, how were you planning to update the Let's Encrypt certificates distributed to the client environments? They only have a 90 day validity period. It seems like you would need some ability to update certificates no matter what you did, so you may as well have separate certificates at that point (not that it's a good idea).

It sounds like you are SOL.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.