How to notarize Electron app for macOS Catalina (10.15)

Stephen
5 min readOct 24, 2019

What a beautiful island like Catalina!

However it probably gonna to be:

What a painful experience to update Electron app for Catalina!

It was exciting after upgrading macOS from Mojave to Catalina and see the beautiful desktop wallpaper, even it took like FOREVER to complete!

The excitement didn’t last more than 1 minute, because I found several apps just become ‘cannot be opened’.

cannot be opened because the developer cannot be verified

Yap, that’s our first experience for Catalina. Lol.

Then we realized all the app has to be notarized to be able to run on Catalina.

The app for uploading to Apple App Store, doesn’t need any notarization!

Then why is it complaining? Because only the new app uploaded to app store, Apple will notarize for you. Those previous apps on app store will all need to re-upload a new build for Apple to notarize for your app. (Yeah, I know it sounds like stupid).

Please note these are ‘regular’ entitlements for production.

production parent entitlements
production child entitlements

You just re-build your app and upload a new build to the app store.

If you are going to distribute your app somewhere for your users to download and install, then you will need to follow the notarization process and configurations for your app and installer.

The above is the tutorial from Apple to show how to do the notarization. In short, it’s:

  1. ZIP the app
  2. Notarize the app
  3. Staple the app

The Apple Notarization could take hours and it’s NOT guaranteed FIFO order. So a 3rd party electron packaging tool like electron-notarize is trying to poll the notarization status until it’s approved.

I know. It definitely becomes more painful when you are trying to change some configuration and do this notarization again to see how it works or not.

Finally, I got a successful notarization and approved!

Let’s try to run our app.

Bummer…., it turns out to crash at starting up.

EXC_BAD_ACCESS (Code Signature Invalid)!

What do you mean!? I didn’t change a bit the original code signing procedure, how could end up this invalid code signature?

Then I search on the internet and found this thread said this has to be added to your entitlements file.

com.apple.security.cs.allow-unsigned-executable-memory

Okay, let’s add and rebuild the app with the notarization. Well, it didn’t crash though, but still it said again:

“cannot be opened because the developer cannot be verified”

We are back to the beginning…

I was assuming my notarization process is correct because it completely followed the Apple guidance. So we are going to re-visit the Electron app builder process.

What is your packaging tool?

I’m using electron-packager for its javascript support and integrated with electron-notarize, also it’s easy to apply to npm script building process, but it doesn’t matter what packaging tool you are using, it’s all about the configuration(entitlements). I’m sure you can find the exactly the same configuration in either electron-forge or electron-builder.

Notarize with Apple ID: You probably already have the ‘@keychain:Application Loader: {appleId}’ password in your local keychain. If you don’t, you can add one by going to XCode->Preferences->Accounts.

If you encounter an authentication problem or cannot find password problem during the notarization, you may want to double check your notarization configuration.

osxNotarize with appleId

Enable hardened runtime: Even though electron-packager will automatically enable this for you when you are doing notarization.

osxSign with hardenedRuntime

Unpack native node modules: If your Electron app still gets this error “cannot be opened because the developer cannot be verified” even you have successfully notarized the app, you may want to check if you have unpack all the native libraries into a folder YOUR_APP.app/Contents/Resources/app.asar.unpacked/

, so that the Apple Notarization can examine and notarize these libraries. Otherwise it just keeps saying that and won’t tell you what exactly the thing you didn’t notarize.

unpack native node modules from afar

This is the full configuration for electron-packager.

macos packager configuration

Test through Developer ID Distribution Application

You definitely want to test your Electron app locally on your Catalina machine. Then let’s build a distributable app first.

build a distributable app

Notarize the installer as well

Notarize the installer

When you are packaging your app into a flatten .pkg installer, you will also need to notarize this .pkg, otherwise you will see the below warning.

pkg can’t be opened

More problems?

If you can successfully install the app and run without “cannot be opened because the developer cannot be verified”. Then your app has been complete notarized.

But still, you may find other errors or issues like: crash, blank screen, unable to connect to the internet, unable to use media devices, unable to open a file via finder,….etc. That’s how painful it is! But don’t be frustrated, the last mile it is!

Fix the entitilements declarations

These are the basic declarations for accessing media devices, network, and file system.

If your app creates a writeable and exeutable memory like evaluating javascript, Python, Perl regular expressions, macros…, you will need:

com.apple.security.cs.allow-jit

If your app does directly modify its executable files, you will need:

com.apple.security.cs.disable-executable-page-protection

If your app dynamically links environment variables you will need:

com.apple.security.cs.allow-dyld-environment-variables

If your app sends Apple Events to other apps, you will need:

com.apple.security.automation.apple-events

Blank(white) screen?!

Below are my entitlements for reference, please note:

Do Not add

com.apple.security.app-sandbox

com.apple.security.inherit

com.apple.security.application-group

for distribution build.

parent entitlements
child(inherit) entitlements

Well, that’s it. Hope these help you to pass the Notarization hell journey. Lol

Feel free to share some feedback!

--

--