114

I have developer server that are used for testing. They have SSL self-signed certificates, which allow us to test the web application over HTTPS, but with prominent warnings that the certificates are not verifiable.

That's fine, but I have a Service Worker that throws an error with the navigator.serviceWorker.register

SecurityError: Failed to register a ServiceWorker: An SSL certificate error occurred when fetching the script.

How do I use a Service Worker with an intranet testing server which has a self-signed certificate?

Keith
  • 150,284
  • 78
  • 298
  • 434
  • @Tom These are internal test systems, there's no budget to buy valid ones. – Keith Aug 02 '16 at 20:33
  • 4
    Buy ? If it's not a wildcard, you can use let's encrypt for free : http://letsencrypt.org/ – Tom Aug 02 '16 at 21:58
  • 9
    If it's just for you to test, you can start the browser with a flag to use http: chrome --unsafely-treat-insecure-origin-as-secure – psimyn Aug 04 '16 at 10:35
  • 5
    @psimyn cheers, that's useful. Is there an equivalent for testing with mobile devices? – Keith Aug 04 '16 at 11:02
  • not that I'm aware of - you can disable for localhost which could work in an emulator. Otherwise just go the free certificate route – psimyn Aug 10 '16 at 09:25
  • You can also use a free SSL/TLS CA like https://letsencrypt.org. It makes your website a valid https. The process will be automatically done using a python program called [Certbot](https://certbot.eff.org). – Majid Apr 21 '18 at 22:52
  • @Majid cheers, but LetsEncrypt has already been mentioned and these servers are Windows/IIS - Certbot doesn't help. – Keith Apr 22 '18 at 08:06
  • @Keith Oh sorry, you are right !! LetsEncrypt is already mentioned :-D Even though maybe it's too late but answers in this [StackOverflow question](https://stackoverflow.com/questions/7580508/getting-chrome-to-accept-self-signed-localhost-certificate) may help others! – Majid Apr 23 '18 at 23:44
  • 7
    Also LetsEncrypt is no good for internal-only systems that are not reachable from the internet. – Cam Jackson Nov 07 '18 at 08:05
  • @Tom Yes, buy. Let's Encrypt requires a fully qualified domain name, not a name in a private top-level domain, and registering a fully qualified domain name is a recurring expense. – Damian Yerrick Jan 13 '20 at 03:54
  • 1
    You shouldn't need a public IP, FQDN, and SSL cert to do basic web development. – Michael Cole Jan 25 '21 at 16:02

11 Answers11

56

As an alternative to using self-signed certificates, you can launch Chrome or Firefox such that it pretends certain domains are secure. For example, using Chrome on a Mac, you can launch it using:

/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ --user-data-dir=/tmp/foo --unsafely-treat-insecure-origin-as-secure=http://www.your.site

Service workers should then work from http://www.your.site.

More info can be found here: Options for testing service workers via HTTP

Edit: Changed --unsafety-... to --unsafely-...

Community
  • 1
  • 1
Chuck
  • 1,004
  • 11
  • 11
  • 24
    Note: The `--allow-insecure-localhost` flag is also helpful when developing locally – vine77 Apr 28 '17 at 12:55
  • 2
    i tried this like this and i still get the same error: ./chrome --unsafely-treat-insecure-origin-as-secure=http://192.168.120.49:3000 . I tried with dir specified too. Please hlep – maths Feb 17 '18 at 00:17
  • 1
    Debugging of service workers is described here: https://www.chromium.org/blink/serviceworker/service-worker-faq – Chilly Code Apr 26 '18 at 19:30
  • 1
    I tired your solutin but I still get the errors and the service worker is not running. Also I tried to add `--ignore-certificate-errors` and no luck my app needs to run on https also on development and we use self signed certificates which makes the sw untestable in chrome :( Does anyone know another workaround for this ? – Nicu May 25 '18 at 08:50
  • 2
    so is the answer No? No self-signed certificates allowed? – user798719 May 28 '18 at 06:59
  • 1
    Whats the point of using SSL if you're just blindly accepting any certificate on your site? This does not protect against man-in-the-middle-attacks at all, if I'm not mistaken. – phil294 Sep 30 '18 at 10:57
  • There's no need of --user-data-dir, unless you want to save everything from the profile in another folder. – Ricardo Martins Jan 17 '20 at 03:29
  • 3
    @phil294, if the certificate can be installed explicitly, it should be ok. I'm working on a webpage that should only be used on a local network. The devices can be prepared by me, and used by regular users. The devices even should not have internet connection. How does a certificate authority help in such a case? I should be able to install any certificate I want. – sanderd17 Feb 04 '20 at 15:36
  • What about on Android (Chrome)? I need to develop for the notches/etc... – Max Waterman Sep 11 '20 at 02:46
26

The accepted answer above didn't work for me. I added the --ignore-certificate-errors to that as suggested by @stef52 for this question Error with Service Worker registration and that worked

chrome.exe --user-data-dir=/tmp/foo --ignore-certificate-errors --unsafely-treat-insecure-origin-as-secure=https://localhost/

OR for MAC users

 ./Google\ Chrome --user-data-dir=/tmp/foo --ignore-certificate-errors --unsafely-treat-insecure-origin-as-secure=https://localhost
AJC
  • 981
  • 10
  • 17
12

For local development we use self signed certs. To overcome the problems relating to local dev on OSX. We did the following:

  • Create your certificate and serve it up
  • Navigate to the https url
  • Open dev tools > security > view certificate
  • drag the certificate icon to the desktop and doubleclick on it, this will open up keychain access.
  • drag the certificate icon to login, open up log-in and double click on the certificate (it should be named with the dev domain or similar) open up the trust dropdown and select always trust. Go back to your app close the window and re-open with https, you should now have 'faux' https for your dev domain.
Lesbaa
  • 1,979
  • 2
  • 12
  • 15
  • 1
    for local development you can just use localhost and no certs of any kind are required for a service worker – user798719 May 28 '18 at 07:00
  • Doesn't work for trusted self signed certificates for Chrome 58+ – Ozil Jun 20 '18 at 10:50
  • @Ozil, I deleted my certificate and carried out the above and it worked fine, that was on OSX Chrome 67. Also, you trust the certificate in your operating system, not in chrome. What set-up are you using? https://letsencrypt.org/docs/certificates-for-localhost/ – Lesbaa Jun 21 '18 at 16:40
  • @user798719 The question does not specify desktop. How do you install a web server onto an iPod touch, iPhone, or iPad in order to perform localhost testing? – Damian Yerrick Jan 20 '20 at 22:37
12

For me working on latest Chrome available v.79. the following works on OS X.

Create new certificates - Only required If your default certificates are expired, which might be the case, if its been long time since Your apache installation.

Create a new certificate for localhost using the following snippet from letsencrypt.org

openssl req -x509 -out server.crt -keyout server.key \
  -newkey rsa:2048 -nodes -sha256 \
  -subj '/CN=localhost' -extensions EXT -config <( \
   printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")

Enable the newly created certificate by placing the created .crt and .key in /usr/local/etc/httpd or wherever Your certificates might be located.

server.key/server.crt should be default names for the certificates, but if You have changed it, it might be better to check the configuration which is located at /usr/local/etc/httpd/extra/httpd-ssl.conf for me

The following lines are the meaningful ones:

SSLCertificateFile "/usr/local/etc/httpd/server.crt"
SSLCertificateKeyFile "/usr/local/etc/httpd/server.key"

then restart the server

Make Your computer trust Your self signed certificates

Click the padlock icon on the left side of the URL, while https://localhost is open Chrome certificate panel On said panel, choose 'certificates' and the window on the right will open up.

Select localhost, and on the bigger icon above 'details', drag the icon to Your desktop.

You should end up with file such as localhost.cer on Your desktop.

Double click this file or right click -> open with Keychain access

Select Category 'All items' and a certificate with name 'localhost' should appear on the right panel.

All items

Double click the 'localhost' on the right panel and the following window should open up

Window

Expand 'trust' and under 'when using this certificate' select 'always trust'

Close the window. Now this certificate should be trusted.

Pasi Matalamäki
  • 1,843
  • 17
  • 14
5

Answers by Pasi Matalamäki and Lesbaa are the most correct. I'm going to explain why and talk through the concepts.

Yes, you might be able to start chrome in a mode that ignores cert errors from your site in dev -- even if you can do that today, my money says that in the future that will change. Therefore, I would not go that route in 2021.

The crux of the issue is that the browsers have the very difficult job of putting the power of PWA and serviceworkers into developers hands, while at the same time keeping those things away from black hat hacker's -- or at least making it practically impossible for someone to setup a malicious PWA that all the browsers will trust and let run.

When you think of the problem from that angle, the right solution is clear. You need a dev environment where your PWA is being served up with a cert that your browser will trust.

Let me say, that as a developer and as an infrastructure professional of decades, this stumped me too. But it shouldn't have.

I see lots of comments saying you shouldn't need a public IP and SSL Cert to do basic web development. I agree. But to be fair, developing a PWA and service workers is not basic web development -- it is powerful web development that has to be secured, as I said earlier.

Also, you don't need a public IP and you don't need to buy a cert -- not for the lone developer or for the enterprise development shop in a corporation.

In any case, you have to get a certificate generated by a CA that your browser trusts. In the context of or corporations internal network and developing internal apps, your infrastructure teams most likely already have a CA that all your company's internal PC's trust and therefore you will get the full lock in your browser. You just have to find out how to get a cert generated by them, and then THAT cert is the one you use with your http-server or whatever you are using to serve it up.

In the context of the developer that isn't in a corp, you just have to create your own CA, then using that CA you generate a certificate. Here is one, of many, good guides on doing that: https://www.ibm.com/docs/en/runbook-automation?topic=certificate-generate-root-ca-key

However, there is an important thing you must do next -- you have to install that CA into your OS so that your OS considers it a trusted third party CA. How you do that on windows and MacOS: https://smallbusiness.chron.com/make-computer-trust-certificate-authority-57649.html

On Linux, here is a good thread on how to do that on one popular flavor: https://superuser.com/questions/437330/how-do-you-add-a-certificate-authority-ca-to-ubuntu

Note, you may not have to, but I also installed the certificate I generated with the CA to my host(s). Probably not necessary.

You may run into issues because the tool you use to generate CA/CRTs outputs in a format that is different from what your OS expects. If you find that is your case, there are plenty of articles that can tell you how to transform certs into various formats.

Now, some readers may be thinking "but how do I get this to work for my entire team, etc". The answer is, you really can't. Not unless your team is on a corporate net with all the PC's managed and already setup to trust a corporate CA, etc. So again, if that is your use case, just find the infrastructure team that owns internal SSL services and have a discussion.

While it may seem a PITA to have to go through all of this, again think about how dangerous it would be if you somehow could get other PCs to trust your cert.

The good news is, when development is done and it is time to deploy, you do end up with a public IP and a cert tied to that IP, etc. So this is really just a dev environment issue.

Well, I suppose not in the case where your app lives on a corporate net and is only accessible internally. In that case you just get a production cert from that same infrastructure team.

Thomas Carlisle
  • 171
  • 3
  • 3
  • 1
    Thomas, I don't see a solution in your answer, and the idea that certain browser tech is "too dangerous" for ordinary people is security obscurity. Making it hard to use doesn't increase security, it increases monopoly. – Michael Cole Dec 09 '21 at 17:20
  • Perhaps it could be clearer, but what I meant by that phrase is that browsers requiring SSL for service workers is appropriate in 2021. If someone is legit developing a service worker, they need to know how to get and use an SSL cert that is trusted by their browser. – Thomas Carlisle Dec 09 '21 at 22:50
  • @ThomasCarlisle I do understand what you mean. I will give an example of why we need to find new ways to handle SSL certs. Have IOT or non IOT device destined to be use into networks that will not necessarily have access to internet, these devices could let you use tools that connect to an API via SSL to gather information it makes available. Would be so easy if it wasn't for Certs. Now these cannot have SSL certs because they are not on internet. Only option would be an internal CA, but it means either convincing the client to let you be on theirs or you need to sell one to them. – Shuryno Jan 18 '23 at 18:43
3

This answer repeats some Chucks' points.

If that specific DomException was happened locally at some address port, when accessing web resource at local machine, one of these latest version of browser launches may had helped:

open -a Opera.app --args --user-data-dir=/tmp/foo --ignore-certificate-errors --unsafely-treat-insecure-origin-as-secure=https://localhost:8111

open -a Brave\ Browser.app --args --user-data-dir=/tmp/foo --ignore-certificate-errors --unsafely-treat-insecure-origin-as-secure=https://localhost:8111

open -a Google\ Chrome.app --args --user-data-dir=/tmp/foo --ignore-certificate-errors --unsafely-treat-insecure-origin-as-secure=https://localhost:8111

Chromium browser did not start with these settings to allow to overcome this specific DomException for using SSL with service worker locally.

This person provided some insights as a story as well for this matter: https://deanhume.com/testing-service-workers-locally-with-self-signed-certificates/

Oleksii Kyslytsyn
  • 2,458
  • 2
  • 27
  • 43
2

For those who are getting error No such file or directory after trying @Chucks accepted answer try below,

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir=/tmp/foo --ignore-certificate-errors --unsafely-treat-insecure-origin-as-secure=https://localhost:1123

More information can be found on this link

Pravin W
  • 2,451
  • 1
  • 20
  • 26
2

Yes, on Firefox 83/84 no problem. This didn't work for me on Chrome 87/88, so I switched.

You shouldn't need a public IP, FDQN, ssl cert, and/or fiddly settings to do basic web development.

Ultimately, I turned off PWA for my application in development.

Michael Cole
  • 15,473
  • 7
  • 79
  • 96
  • 4
    Firefox steps away from PWA. Chrome makes it impossible to dev locally. Looks like you made the right choice. – OXiGEN Jan 28 '21 at 07:21
2

Yes, you can use self-signed SSL in your chrome browser as localhost.

At first, chrome will not allow for a self-signed SSL local server but you can enable it by:

  1. Type Chrome://flags in the search bar in a new tab
  2. Now inside Chrome flags search for Allow invalid certificates for resource load from localhost. And Enabled it.
  • This works wonderfully. I'm surprised more answers don't mention it. Maybe it's new? Much easier to deal with than other options. – Iguananaut Jun 27 '23 at 17:02
1

For me, ignoring certificates or setting the insecure origin flag for mobile device did not work.

However, portforwarding did the trick. Service workers are allowed to run on localhost no matter if its signed with certificate and communicating through SSL, so basically you let your mobile device think that it runs on localhost but actually you are forwarding it to the real localhost on server machine. This can be achieved by each of these 2 methods:

kudlohlavec
  • 464
  • 4
  • 18
1

For Linux - Use the following steps:

  1. Find the chrome in Linux using:

    > whereis google-chrome-stable
    

    eg: In my case, the output is:

    /usr/bin/google-chrome-stable /usr/share/man/man1/google-chrome-stable.1.gz
    
  2. Go to that directory. In my case it is bin

    > cd /bin/
    
  3. Run the following command

    > google-chrome-stable --user-data-dir=/tmp/foo --ignore-certificate-errors --unsafely-treat-insecure-origin-as-secure=https://localhost/
    
shA.t
  • 16,580
  • 5
  • 54
  • 111
Ela
  • 91
  • 6