How to Notarize your Electron App
Dunschtig,24 Oktoober, 2019

I have been spending a lot of time on figuring out how to comply with the new apple requirements about Notarizing your app. In short, unless your Mac OS X app is notarized, it would be impossible to distribute it directly to users without nasty warnings that even prevent the app to be installed by the user without changing security settings.

So straight to the point, after hours and trial an error here is how too have your application notarized (OS X 10.14.6).

David.dev screenshot

Step 1 - Pre-requisites

For starters you need electron-builder, a valid Apple ID signing certificate and electron-notarize. I am using the latest electron at the time of this writing that is 6.0.12

Step 2 using electron-notarize

you need to have afterSignHook.js (that we builder will use to run the notarisation process) and on step 3 the entitlements.mac.plist

const fs = require('fs');  
const path = require('path');  
var electron\_notarize = require('electron-notarize');  
require('dotenv').config();  
module.exports = async function(params) {  
  // Only notarize the app on Mac OS only.  
  if (process.platform !== 'darwin') {  
    return;  
  }  
  console.log('afterSign hook triggered', params);  
  // Same appId in electron-builder.  
  let appId = 'dev.david.elektro'  
  let appPath = path.join(params.appOutDir, \`${params.packager.appInfo.productFilename}.app\`);  
  if (!fs.existsSync(appPath)) {  
    throw new Error(\`Cannot find application at: ${appPath}\`);  
  }  
  console.log(\`Notarizing ${appId} found at ${appPath}\`);  
  try {  
    await electron\_notarize.notarize({  
      appBundleId: appId,  
      appPath: appPath,  
      appleId: process.env.appleId, // this is your apple ID it should be stored in an .env file  
      appleIdPassword: process.env.appleIdPassword, // this is NOT your apple ID password. You need to   
      //create an application specific password from https://appleid.apple.com under "security" you can generate  
      //such a password   
      ascProvider: process.env.appleIdProvider // this is only needed if you have multiple developer  
      // profiles linked to your apple ID.   
    });  
  } catch (error) {  
    console.error(error);  
  }  
  console.log(\`Done notarizing ${appId}\`);  
};

all this might seems trivial but the issue with the application specific password + ascProvider to select the right developer account fi you have multiple ones took hours to fix!

Step 3

You now need an entitlements file in your build folder. In my case is /resources but it can be anywhere as long as it matches what is on package.json

<?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>

Step 4

Let’s glue it all together in your package.json file

So your package.json will look like this:

{  
  "name": "elektro",  
  "version": "1.0.0",  
  "description": "elektro editor",  
  "main": "main.js",  
  "scripts": {  
    "start": "electron .",  
    "build": "electron-builder"  
  },  
  "author": "david.dev",  
  "license": "ISC",  
  "dependencies": {  
    "electron-is-dev": "^1.1.0"  
  },  
  "devDependencies": {  
    "electron": "^6.0.12",  
    "electron-builder": "^21.2.0",  
    "electron-packager": "^14.0.6",  
    "electron-notarize": "^0.1.1"  
  },  
  "build": {  
    "appId": "dev.david.elektro",  
    "afterSign": "./afterSignHook.js",  
    "directories": {  
      "buildResources": "resources"  
    },  
    "extraResources": \[  
      {  
        "from": "./images/elektro.png",  
        "to": "elektro.png"  
      }  
    \],  
    "mac": {  
      "hardenedRuntime": true,  
      "entitlements": "./resources/entitlements.mac.plist"  
    },  
    "dmg": {  
        "background": "dmg.png"  
    }  
  }  
}

now you just run npm run build and all should work file and you will have a notarized app and the relevant .dmg file. You can customise the the line “dmg: background” to include your own background for the dmg. It is not required so if you remove this option you will still have a working dmg. Also don’t forget to have and icon.icns file in your builder folder (in the example above is resources) else you will not have a specific icon. The “extraResources” bit is also not needed in all cases (I required that because of a tray icon).

Conclusions and other guides

Electron is moving very fast (and so is Apple with this new notarization requirements) but if you follow these steps you should be ready to go and get this result David.dev screenshot

So the warning is gone but it will still notice the user that the app was downloaded for the internet but it does confirm that apple did check it for malicious software so it is notarized.

There is another good guide that helped me through the notarizion process here.