Firma e Notarizzazione
La firma del codice (code signing) e la notarizzazione sono necessarie per distribuire applicazioni Electron in modo professionale. Senza firma, gli utenti riceveranno avvisi di sicurezza dal sistema operativo.
Perché Firmare
- Windows: Senza firma, SmartScreen mostra un avviso “Windows ha protetto il tuo PC”
- macOS: Da macOS Catalina, le app non notarizzate non possono essere aperte
- Fiducia: La firma garantisce che l’app non è stata manomessa dopo la distribuzione
- Auto-update: Gli aggiornamenti automatici richiedono la firma su macOS
Firma su Windows
Ottenere un Certificato
Per firmare su Windows hai bisogno di un certificato di code signing. Puoi acquistarlo da autorità di certificazione come DigiCert, Sectigo o GlobalSign.
Configurazione con electron-builder
# electron-builder.yml
win:
target: nsis
signingHashAlgorithms:
- sha256
certificateFile: ./cert/certificate.pfx
certificatePassword: ${WIN_CSC_KEY_PASSWORD}
Oppure tramite variabili d’ambiente:
# Variabili d'ambiente per la firma Windows
export WIN_CSC_LINK=./cert/certificate.pfx
export WIN_CSC_KEY_PASSWORD=la-tua-password
Firma con Electron Forge
// forge.config.js
module.exports = {
packagerConfig: {
windowsSign: {
certificateFile: './cert/certificate.pfx',
certificatePassword: process.env.WIN_CSC_KEY_PASSWORD,
},
},
};
Firma e Notarizzazione su macOS
Prerequisiti
- Un Apple Developer Account ($99/anno)
- Un certificato Developer ID Application da Apple
- Un App-Specific Password per la notarizzazione
Configurazione con electron-builder
# electron-builder.yml
mac:
target:
- dmg
- zip
identity: "Developer ID Application: Tuo Nome (TEAM_ID)"
hardenedRuntime: true
gatekeeperAssess: false
entitlements: entitlements.mac.plist
entitlementsInherit: entitlements.mac.plist
afterSign: scripts/notarize.js
File Entitlements
<!-- entitlements.mac.plist -->
<?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>
Script di Notarizzazione
// scripts/notarize.js
const { notarize } = require('@electron/notarize');
exports.default = async function notarizing(context) {
const { electronPlatformName, appOutDir } = context;
if (electronPlatformName !== 'darwin') return;
const appName = context.packager.appInfo.productFilename;
console.log('Notarizzazione in corso...');
await notarize({
appBundleId: 'com.example.miaapp',
appPath: `${appOutDir}/${appName}.app`,
appleId: process.env.APPLE_ID,
appleIdPassword: process.env.APPLE_ID_PASSWORD,
teamId: process.env.APPLE_TEAM_ID,
});
console.log('Notarizzazione completata!');
};
Variabili d’Ambiente per macOS
export APPLE_ID=tuo@email.com
export APPLE_ID_PASSWORD=app-specific-password
export APPLE_TEAM_ID=ABCD123456
Firma con Electron Forge (macOS)
// forge.config.js
module.exports = {
packagerConfig: {
osxSign: {
identity: 'Developer ID Application: Tuo Nome (TEAM_ID)',
hardenedRuntime: true,
entitlements: 'entitlements.mac.plist',
'entitlements-inherit': 'entitlements.mac.plist',
},
osxNotarize: {
appleId: process.env.APPLE_ID,
appleIdPassword: process.env.APPLE_ID_PASSWORD,
teamId: process.env.APPLE_TEAM_ID,
},
},
};
CI/CD con GitHub Actions
# .github/workflows/build.yml
name: Build & Release
on:
push:
tags: ['v*']
jobs:
build-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx electron-builder --win --publish always
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
WIN_CSC_LINK: ${{ secrets.WIN_CSC_LINK }}
WIN_CSC_KEY_PASSWORD: ${{ secrets.WIN_CSC_KEY_PASSWORD }}
build-macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx electron-builder --mac --publish always
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
CSC_LINK: ${{ secrets.MAC_CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.MAC_CSC_KEY_PASSWORD }}
build-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx electron-builder --linux --publish always
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Best Practice
- Non includere i certificati nel repository — usa variabili d’ambiente o secret management
- Automatizza la firma nella CI/CD — evita errori manuali
- Testa le build firmate — verifica che la firma e la notarizzazione funzionino correttamente
- Rinnova i certificati prima della scadenza — le app firmate con certificati scaduti non funzionano
- Usa hardened runtime su macOS — è obbligatorio per la notarizzazione