Tianpai Blog

MacOS Code Signing & Notarization for Electron Apps

Apparently, I cannot get Kairos running (without some magic) or even auto-update on MacOS. There is an entrance fee. I don’t want to go through this again. So here is a complete guide for signing and notarizing Electron apps for distribution outside the Mac App Store.

Prerequisites

1. Create Developer ID Application Certificate

  1. Go to https://developer.apple.com/account/resources/certificates/list
  2. Click + to create new certificate
  3. Select Developer ID Application (last option under Software)
  4. Select G2 Sub-CA (Xcode 11.4.1 or later)
  5. Upload a Certificate Signing Request (CSR)

Creating the CSR

  1. Open Keychain Access
  2. Menu → Keychain AccessCertificate AssistantRequest a Certificate From a Certificate Authority…
  3. Fill in:
    • User Email: your Apple ID email
    • Common Name: your name
    • CA Email Address: leave blank
    • Request is: Saved to disk
  4. Save the .certSigningRequest file
  5. Upload to Apple Developer portal

Download and Install

  1. Download the generated .cer file
  2. Double-click to install
  3. Select login keychain when prompted

2. Fix “Certificate Not Trusted” Error

If you see “certificate is not trusted” in red:

  1. Go to https://www.apple.com/certificateauthority/
  2. Download Developer ID - G2 (under “Subordinate Certification Authority”)
  3. Double-click to install to login keychain

Your certificate should now show as valid.

3. Configure electron-builder

Add to electron-builder.yml:

1mac:
2  category: public.app-category.productivity
3  target:
4    - dmg
5    - zip
6  icon: build/icon.icns
7  hardenedRuntime: true # Required for notarization
8  gatekeeperAssess: false
9  notarize: true # Enable automatic notarization

electron-builder automatically finds Developer ID Application certificates in your keychain.

4. Create App-Specific Password

Required for notarization:

  1. Go to https://appleid.apple.com → Sign In
  2. App-Specific Passwords → Generate
  3. Name it (e.g., “Electron Notarization”)
  4. Save the password (format: xxxx-xxxx-xxxx-xxxx)

5. Local Build with Signing

Set environment variables and build:

1export APPLE_ID="[email protected]"
2export APPLE_APP_SPECIFIC_PASSWORD="xxxx-xxxx-xxxx-xxxx"
3export APPLE_TEAM_ID="XXXXXXXXXX"  # 10-char code from certificate
4
5npm run build:mac

You should see:

signing         file=dist/mac-arm64/YourApp.app identityName=...
notarizing      file=dist/mac-arm64/YourApp.app
notarization successful

6. Verify Signing & Notarization

1# Check code signature
2codesign -dv --verbose=4 dist/mac-arm64/YourApp.app
3
4# Check notarization (should say "source=Notarized Developer ID")
5spctl -a -vvv -t install dist/mac-arm64/YourApp.app

7. CI/CD Setup (GitHub Actions)

Export Certificate as .p12

  1. Open Keychain Access
  2. Find Developer ID Application: Your Name certificate
  3. Right-click → Export → save as .p12
  4. Set a strong password

Base64 Encode

1base64 -i ~/Desktop/Certificates.p12 | pbcopy

GitHub Secrets

Go to repo → Settings → Secrets and variables → Actions → Repository secrets

Add these secrets:

Secret NameValue
CSC_LINKBase64-encoded .p12 (from clipboard)
CSC_KEY_PASSWORDPassword you set for .p12
APPLE_ID[email protected]
APPLE_APP_SPECIFIC_PASSWORDxxxx-xxxx-xxxx-xxxx
APPLE_TEAM_ID10-character team ID

Workflow Configuration

1- name: Build Electron app
2  run: npm run build:mac
3  env:
4    GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5    CSC_LINK: ${{ secrets.CSC_LINK }}
6    CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
7    APPLE_ID: ${{ secrets.APPLE_ID }}
8    APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
9    APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}

Finding Your Team ID

Look at your certificate in Keychain Access:

Developer ID Application: Your Name (XXXXXXXXXX)
                                      ^^^^^^^^^^
                                      This is your Team ID

Or find it at https://developer.apple.com/account → Membership Details.

Notarization Time

Notarization uploads your app to Apple for automated malware scanning:

  • Usually takes 10-40 minutes (sometimes longer than build time)
  • Fully automated (no human review like App Store)
  • Happens on every build

Troubleshooting

“Certificate not trusted”

Install Apple’s intermediate certificate from https://www.apple.com/certificateauthority/

Notarization fails with “team ID” error

Ensure APPLE_TEAM_ID is set and matches your certificate.

CI build fails to find certificate

Verify CSC_LINK is properly base64 encoded and CSC_KEY_PASSWORD is correct.

“No signing identity found”

The certificate must have the private key attached. When exporting to .p12, make sure to export from “My Certificates” category which includes the private key.

<< Previous Post

|

Next Post >>

#Project #Code Signing #Technical #ElectronJS