We had a similar situation, with an Electron application for MacOS using auto-update, and we needed to switch to a new certificate without making everyone download and re-install the application manually. The auto-update process needs to recognize the new certificate. Rightfully so, the old version will refuse to update if the new certificate is not recognized.
Our strategy was:
- look at the
designated requirement
(or DR) of the application, when signed with the old certificate, using codesign -d -v -r - <path-to-app>
- look at the
designated requirement
of the application when signed with the new certificate
- place the combined
designated requirement
, that includes both certificates, into an electron-builder-requirements.txt
file
- make sure that you do not include the
identifier
in the combined designated requirement
string
- make a reference to the
electron-builder-requirements.txt
in the electron-builder.yaml
file (add a line under mac:
like this requirements: electron-builder-requirements.txt
)
- publish a new version of the app, signed with the old certificate, but with the DR that contains information about both certificates
- wait until nearly everyone has the version running on their desktop that includes mention of both certificates in the DR
- update the build so that it uses the new certificate instead, and remove the
electron-builder-requirements.txt
file
- release a new version of the app signed with the new certificate (no requirements file is needed, and it will list only its own cert in the DR)
An older version of the application that has a DR that includes information about both certificates will allow an auto-update to a new version that uses either certificate.
I found this document about signing code manually helpful in understanding the "designated requirement".
Update: here's an example of the electron-builder-requirements.txt
file (I've modified some of the letters/numbers for privacy purposes):
designated => certificate leaf = H"2323ce6b0XXXXXXXX39f2064be999999997272b1" or anchor apple generic and certificate 1[field.1.2.840.199995.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.199995.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = "6ZXXXXXXUY"