Notarize Electron apps on Mac OS automatically with electron-builder & electron-notarize

Twitter Archive Eraser
4 min readMay 27, 2019

Starting with macOS 10.14.5, Apple is enforcing apps to be notarized for new developer IDs. Users of your app will get this scary message when they try to open the dmg:

Worse, if you upgrade to macOS 10.14.5 you wouldn’t be able to build your app at all using electron-builder (fix in progress).

Hint: to proceed with opening the dmg anyway on macOS 10.14.5, you can simply right click the select open. The warning window will now have an ‘open’ button you can click to proceed.

This post describes how we notarized our app Twitter Archive Eraser. Make sure to check it out if you’d like to clean up your Twitter account and delete old tweets: https://martani.github.io/Twitter-Archive-Eraser.

Notarize electron apps with electron-builder & electron-notarize

In order to notarize your electron app, it needs to be built with the Hardened Runtime capability. To enable this for your app, add the ‘hardenedRuntime’ property to your ‘mac’ target in electron-builder settings (in packages.json or electron-builder.json depending on your setup).

"mac": {
"icon": "./build/icon.icns",
"hardenedRuntime": true,
"entitlements": "./build/entitlements.mac.inherit.plist",
"target": ["dmg", "zip"]
}

Note: ‘hardenedRuntime’ was introduced in electron-builder 20.41.0 ; you need to specifically reference that version or higher in your packages.json.

You also need to have a valid entitlements file, with at least the following entitlements:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>

Do not forget to reference the entitlements file in the ‘mac’ build target as shown above.

Manually test your notarization settings

To ensure your notarization settings are correct, you can run the notarization steps manually as following:

  1. Build your electron app normally (ensure it’s signed!)
  2. Run xcrun altool --notarize-app -f <your .app file here> --primary-bundle-id <your app id> -u username -p password
  3. You’ll get a GUID if the package uploads successfully, to follow the notarization progress, run: xcrun altool --notarization-info <GUID from previous request> -u username -p password
  4. Once the notarization is successful, staple the app as follows: xcrun stapler staple <your .app file here>
  5. And verify by running: spctl -a -v <your .app file here>

Refer to this stackoverflow thread which has much more details about this process: https://stackoverflow.com/a/53121755

Make sure to try out starting the app after this process, if some entitlements are missing, the app might be broken after notarization.

Automate app notarization with electron-notarize and electron-builder hooks

electron-notarize is a package that automates the notarization of your electron apps. You’d need to trigger the notarization through electron-notarize after the app is signed and before the final package is built. In order to do this, you can use electron-builder hooks specifically the afterSign hook.

U̵n̵f̵o̵r̵t̵u̵n̵a̵t̵e̵l̵y̵ ̵t̵h̵e̵ ̵a̵f̵t̵e̵r̵S̵i̵g̵n̵ ̵h̵o̵o̵k̵ ̵o̵n̵ ̵M̵a̵c̵ ̵O̵S̵ ̵i̵s̵ ̵b̵r̵o̵k̵e̵n̵,̵ ̵i̵t̵ ̵g̵e̵t̵s̵ ̵t̵r̵i̵g̵g̵e̵r̵e̵d̵ ̵*̵b̵e̵f̵o̵r̵e̵*̵ ̵t̵h̵e̵ ̵s̵i̵g̵n̵i̵n̵g̵ ̵p̵r̵o̵c̵e̵s̵s̵ ̵e̵v̵e̵n̵ ̵s̵t̵a̵r̵t̵s̵.̵ ̵T̵h̵e̵r̵e̵ ̵i̵s̵ ̵a̵n̵ ̵o̵n̵g̵o̵i̵n̵g̵ ̵f̵i̵x̵ ̵f̵o̵r̵ ̵t̵h̵i̵s̵ ̵w̵h̵i̵c̵h̵ ̵s̵h̵o̵u̵l̵d̵ ̵l̵a̵n̵d̵ ̵s̵o̵o̵n̵ ̵(̵a̵s̵ ̵o̵f̵ ̵2̵0̵1̵9̵–̵0̵5̵–̵2̵5̵)̵.̵ ̵I̵n̵ ̵t̵h̵e̵ ̵m̵e̵a̵n̵t̵i̵m̵e̵,̵ ̵c̵h̵e̵c̵k̵ ̵t̵h̵e̵ ̵c̵o̵m̵m̵e̵n̵t̵s̵ ̵o̵n̵ ̵h̵o̵w̵ ̵t̵o̵ ̵r̵u̵n̵ ̵t̵h̵e̵ ̵f̵i̵x̵ ̵l̵o̵c̵a̵l̵l̵y̵.̵

afterSign hook is properly working in Mac as electron-builder 20.42.0.

Add a file named afterSignHook.js with the following content:

You now need to reference this hook from your electron-builder config as follows:

{
"productName": "Twitter Archive Eraser",
"appId": "martani.Twitter-Archive-Eraser",
...
"afterSign": "./afterSignHook.js",
...
}

You need to add you app email and password as environment variables appleId and appleIdPassword.

Once you run electron-builder, it will run the notarization process automatically (it takes some ~5 to ~15 minutes) then packages the app.

Unfortunately, even after the app is notarized, the dmg will still not open on macOS 10.14.5. It turns out that the dmg in that case should not be signed in order for it to work properly. Meaning, what works on macOS 10.14.5 and higher is: a non-signed non-notarized dmg that contains a signed + notarized app.

Update: this is fixed by default in electron-builder 20.44.4 and the dmg is not signed by default.

T̵o̵ ̵f̵i̵x̵ ̵t̵h̵i̵s̵,̵ ̵y̵o̵u̵’̵d̵ ̵n̵e̵e̵d̵ ̵t̵o̵ ̵s̵k̵i̵p̵ ̵s̵i̵g̵n̵i̵n̵g̵ ̵t̵h̵e̵ ̵d̵m̵g̵.̵ ̵A̵s̵ ̵o̵f̵ ̵e̵l̵e̵c̵t̵r̵o̵n̵-̵b̵u̵i̵l̵d̵e̵r̵ ̵2̵0̵.̵4̵2̵.̵0̵,̵ ̵t̵h̵e̵r̵e̵ ̵i̵s̵ ̵n̵o̵ ̵w̵a̵y̵ ̵t̵o̵ ̵d̵o̵ ̵t̵h̵i̵s̵ ̵e̵x̵c̵e̵p̵t̵ ̵c̵h̵a̵n̵g̵i̵n̵g̵ ̵t̵h̵e̵ ̵f̵i̵l̵e̵ ̵.̵/̵n̵o̵d̵e̵_̵m̵o̵d̵u̵l̵e̵s̵/̵d̵m̵g̵-̵b̵u̵i̵l̵d̵e̵r̵/̵o̵u̵t̵/̵d̵m̵g̵.̵j̵s̵ ̵m̵a̵n̵u̵a̵l̵l̵y̵.̵ ̵(̵T̵h̵e̵r̵e̵ ̵i̵s̵ ̵w̵o̵r̵k̵ ̵i̵n̵ ̵p̵r̵o̵g̵r̵e̵s̵s̵ ̵t̵o̵ ̵a̵d̵d̵ ̵a̵n̵ ̵o̵p̵t̵i̵o̵n̵ ̵t̵o̵ ̵d̵i̵s̵a̵b̵l̵e̵ ̵d̵m̵g̵ ̵s̵i̵g̵n̵i̵n̵g̵.̵)̵
̵O̵p̵e̵n̵ ̵.̵/̵n̵o̵d̵e̵_̵m̵o̵d̵u̵l̵e̵s̵/̵d̵m̵g̵-̵b̵u̵i̵l̵d̵e̵r̵/̵o̵u̵t̵/̵d̵m̵g̵.̵j̵s̵ ̵a̵n̵d̵ ̵r̵e̵m̵o̵v̵e̵/̵c̵o̵m̵m̵e̵n̵t̵ ̵t̵h̵e̵ ̵f̵o̵l̵l̵o̵w̵i̵n̵g̵ ̵l̵i̵n̵e̵:̵

̵y̵i̵el̵d̵ ̵_̵t̵h̵i̵s̵.̵s̵i̵g̵n̵D̵m̵g̵(̵a̵r̵t̵i̵f̵a̵c̵t̵P̵a̵t̵h̵)̵;̵

And voila! your app should now open correctly without any warning signs on macOS 10.14.5(except the usual dialog that it’s downloaded from the internet).

This post describes how we notarized our app Twitter Archive Eraser. Make sure to check it out if you’d like to clean up your Twitter account and delete old tweets: https://martani.github.io/Twitter-Archive-Eraser.

--

--

Twitter Archive Eraser

Bulk delete old tweets & DMs in one go — well beyond the 3200 limit. We help you clean up your Twitter profile — while keeping your account and best tweets.