Sign My Mac App Electron How

  1. Electron Mac App
  2. Electron App Store
  3. How To Make An Electron App
  4. Electron Mac App Store
  5. Microsoft Electron Apps
  6. Sign My Mac App Electron How To
  7. How To Run Electron App

After too many hours spent on preparing a biorhythm sample app for publishing in App Store, I think I have a useful recipe that this articleintends to share.

If you are TL;DRing and just want a signing sequence that is known to work, check this script.The enclosing folder is the sample app; it includes the necessary entitlement files, but doesnot include the provisioning profiles that you will have to obtain using your Apple developer account.

'dist': 'electron-builder -publish always' in your package.json. Set your version in your application package.json to 1.9.0-snapshot (or 1.9.0-master or whatever you want your development channel to be named). This will publish a file named snapshot.yml and a build named something-snapshot.exe (and corresponding for mac) to S3. Two of the most popular Mac programming text editors, TextMate 2 and Sublime Text 3, weigh in at 32MB and 28MB respectively while Atom is an unnecessarily hefty 219MB — a full 7x more bulk. To find a native editor that heavy, one has to download a full-blown IDE with everything but the kitchen sink like Coda. Apple Now Rejects Electron Apps from Mac App Store. On Monday November 04, 2019 @01:20PM Homepage Journal. Why in the world would you. After running this command, Electron will do its magic and create an Electron app that points to the URL specified in your main.js file.

This article is not intended to be a complete documentation of Electron packagingtools (electron-packager, electron-osx-sign, electron-osx-flat). They have officialdocumentation for that. I just want to clarify some pitfalls related to MacOS packaging.

Darwin and MAS packaging

MacOS applications can be packaged in two flavors: Darwin and MAS ('Mac App Store').The MAS format is newer, and it is (obviously) intended for distribution via App Store.MAS apps are also sandboxed (more about this later).

Apps from the Store are the most trusted. Only MAS apps run straight out-of-the-box withoutcomplaints, but you can configure security to trust properly signed Darwin apps as well.

Figure 1: System Preferences, configuration of security regarding signed and MAS apps

Unsigned apps won't run right away in recent versions of MacOS. The userneeds to authorize every individual app in the System Preferences panel shown above. (A usefultrick is to Option-click the unsigned app: a dialog gives the option of authorizingit, just like it used to be in older versions of OS X.)

So, as a developer, you have three ways to distribute your app: MAS, signed Darwin, andunsigned Darwin. I don't recommend wide distribution of unsigned apps due to securityrisks.But, if you simply don't want to deal with app signing, you use the electron-packager tool andnothing more. You may want to read the next three sections of this article, and you are good to go.

In order to sign a MAS or Darwin package, you need a developer certificatesigned by Apple, and to get it you need to enroll the Apple Developer Program, which costs US$ 99/year.This is why there still are so many unsigned apps out there. At least the US$ 99 fee buys you accessto both iOS and MacOS; in the past, you'd have to play $99 for each platform!

Command-line development tools

In order to generate a MacOS package, you need Xcode installed, as well as Xcodecommand-line tools, since Electron builds are carried out outside of the IDE:

MacOS icon format

The application icon is one of the dustiest corners of every platform, I guess. Windowsstill uses the ICO format, and Mac demands icons in a certain ICNS format, that most graphical toolscannot generate.

Electron Mac App

ICNS is actually a bundle of images, typically the same icon scaled down to varying sizes.There are online tools, free and paid, that generate the ICNS icon to be supplied toelectron-packager in order to replace the default Electron icon.

But no external toolis actually necessary. Check this script in my sample app. It takes the original icon (that should be of 1024x1024 size)and creates the ICNS icon. The script only uses CLI development tools.

Certificates

Wnen you enroll the Developer Program, you can request the certificates manually (creatinga certificate request CSR using Keychain, uploading the CSR to developer.apple.com, etc.)but it is much, much easier to let Xcode do it for you.

Figure 2: Xcode tool showing the developer certificates and provisioning profiles

There are five certificates, or identities, related to Mac app signing:

Development certificate: allows to run a signed (and, if MAS, sandboxed) appon your own machine, and also on other development/testing machines registered at developer.apple.com.A maximum of 100 machines per team can be registered, so it is not good for distribution.In order to test a MAS app, you must sign it with this certificate, otherwise the app willnot run in sandboxed mode.

Developer ID application: to sign an app (Darwin or MAS) that you intend to distributeoutside of App Store.

Developer ID installer: to sign the package of an app that you intend to distribute outsideof App Store. (Yes, there is one certificate for the app itself and another for the package.)

Mac App Distribution (or 3rd Party Mac Developer Application): to sign a MAS appthat will be submitted to App Store. The app signed with this certificate won't run anywhere, not evenin the developer's machine, this is not a bug! It will only run when signed off by Apple,and the signed off version is available only at App Store.

Electron App Store

Mac Installer Distribution (or 3rd Party Mac Developer Installer): to sign MAS packages to be submitted to App Store.

By and large, the Electron tool electron-osx-sign will pick the right certificate for eachsituation:

  • When the --type=development parameter is passed, the tool selects the Development certificate.
  • The 'Developer ID' certificate pair is selected when signing Darwin apps, because they can only be distributed outside of App Store.
  • The 'Mac Distribution' pair is selected when signing MAS apps, assuming that they will be uploaded to App Store.

You only need to pass the identity parameter in case you belong to more than one developmentteam (i.e. you have more than one Apple Developer account). But it is important to clarify the roleof each certificate, because the nomenclature is so confusing.

The 'Developer ID' identity must also be passed when you sign a MAS package for direct distribution, outsideof App Store. But most apps outside App Store will choose Darwin over MAS format, because of sandboxing limitations (explained in the next section).

Finally, it is worth to mention that the private keys of these certificates must be protected(i.e. the developer's machine must be physically secure, or use disk encryption). The private keysare not uploaded to developer.apple.com, so if you need to use the same certificates in more thanone machine, you must copy the private keys somehow. The easiest way is to use Xcode's Export DeveloperAccounts.

Provisioning profiles and app IDs

Sign my mac app electron how do i

Then we have 'provisioning profiles', another big source of confusion. They are only necessary whensigning MAS apps. If you are signing Darwin apps, you can ignore this section. This may be anotherreason why so many developers loathe the MAS format and the Mac App Store.

A provisioning profile is a secure bind of one developer certificate, one App ID, a list of machines(in case the app should only run on registered computers), and a list of Apple services that the appwants to use (e.g. Game Center, iCloud, in-app purchases).

Since each provisioningprofile is tied to a particular certificate, you need at least two per MAS app: a development provisioningprofile to run in developer machines, and a production profile that is only used to sign the package thatis sent to App Store.

For apps developed entirely within the Xcode IDE, the provisioning profiles are automatically created. The App ID must be created in developer.apple.com, but even that is optional for apps that don't use any Apple services.I prefer to always create the App ID, just in case you want to use Apple services in a future version.Since Electron apps cannot use the Xcode IDE, we need to createand download the provisioning profiles manually, and having one profile per App ID is easier to handlethan having to cope with the 'wildcard' ID.

Figure 3: developer.apple.com, App ID registration page
Figure 4: developer.apple.com, development provisioning profile page
Figure 5: developer.apple.com, production provisioning profile page

Note that I created two production provisioning profiles: one to sign for App Store, another to sign fordistribution outside the store. I did that because I was playing with all possible signing modes.

IMPORTANT: it is always necessary to supply a provisioning profile when signing MAS packages withelectron-osx-sign. The Electron documentation does not tell you that! You must pass the developmentprofile when the --type=development parameter is used. The app won't run without it.

And don't forget to supply the production profile when signing for App Store, otherwise the package willbe rejected by Application Loader.

Sandboxing and entitlements

MAS apps run in sandboxed mode. This means that the app does not have access to the filesystem, except for itsown configuration folder (a folder like $HOME/Library/Containers/app_id/Data/). Every feature used by theapp (network access, network services, broader filesystem access, etc. etc.) must be explicitly allowed by a static list of entitlements.

The App Store review process does check whether the requested entitlements are congruent to the app's actualrequirements. Adding a laundry list of entitlements 'just to be safe' will probably cost a rejection.

In theory, sandboxing is a great idea: it gives Mac apps a security level more like iOS. In practice, it bringsa number of difficulties and limitations. Many developers don't like it, many powerful apps can't operate insandboxed mode, and that's why so many nice Mac apps are not being distributed via App Store.

In the specific case of Electron apps, the most typical problem is using some Node.js or Electron packagethat is not prepared to run in sandboxed mode. The problems may be subtle and difficult to debug.For example, the Electron API app.makeSingleInstance() causes the app to fail because it callsbind(), which is forbidden in sandboxed mode. Your program will fail if it uses this API. (On theother hand, a MAS app is automatically prevented from running more than one instance, so you don't loseanything by not using this particular API.)

Assuming that you simply must publish your app in Mac App Store, you need to test your app in sandboxed modeearly and often.Note that packaging it as MAS is not enough to put the app in sandboxed mode. You need to sign it aswell, using the development provisioning profile and supplying a list of entitlements. Only then you willhave a true notion how the app is behaving. If you forget to sign the MAS package, it will run with unlimitedpermissions just like a Darwin-packaged app, and you are not testing it at all!

If there are problems, a good place to start looking for answers is the MacOS's Console app (found inUtilities folder). In the figure below, I put the name of my app in the filter, so I only see the relevantconsole messages:

Figure 6: Console tool showing system messages for sandboxed Biorhythmics app

Since you can't write files in arbitrary folders of the filesystem, and in principle you don't know theabsolute path of thesandbox folder, you should query it by calling app.getPath('userData') and writing files in thisfolder only. There are specific entitlements that 'punch a temporary hole' in the sandbox strictly forloading and saving files anywhere in the filesystem, so e.g. a text editor or graphical tool can still work insandboxed mode. Consult the Apple documentation for more details.

In theory, electron-osx-sign tool supplies the entitlements automatically. But I found that I neededto create entitlement files manually to end up with a valid signed package. This is another thing that thetool's documentation does not tell you.

Sign My Mac App Electron How

How To Make An Electron App

Wrapping it up

Finally, let's show the final recipe: the 'pkg' script. This script is used to sign the MAS package of the Biorhythmics sample app. Feel free to copy and adapt it to your own project.

The pkg script signs the MAS package with development profile by default. Passing 'release' as the firstparameter signs the package for upload to Mac App Store. Note that, in either case, it expects asuitable provisioning profile at $HOME; it is up to you to create and download them, as explainedbefore. (Provisioning profiles are developer-, app- and machine-specific, so it would not make sense tosupply my own profiles, not even as samples.)

The parentand childentitlement files are included, since their contents are not secret and can be retrieved by any user that installs Biorhythmics from App Store. There are two of them because child processes need to inherit theparent entitlements, and Electron creates one child (renderer) process per window. The child entitlement file must never be changed, because child processes can only inherit if thechild entitlements are exactly {app-sandbox, inherit} — no more, no less.

If you copy my parent entitlement file to your project, don't forget to replace the application_groupsproperty by your own TeamID-AppID (or by some other guaranteedly unique name).

The version supplied through the --build-version=a.bb.cc parameter has a strict format:a.bb is the user-visible software version, while cc is the build number. If yousubmit a new build for the same version (e.g. in case the first build was rejected or you detecteda bug before publishing) you need to bump the build number.

Electron Mac App Store

Finally, the script for Darwin package signing is also provided. Once you sign an app this way, you can distribute it to anyone,and the package is secure against impersonation or malicious changes.

Microsoft Electron Apps

The pkg_darwin script is much simpler than the MAS script, because there are no entitlements nor provisioning profiles.

Sign My Mac App Electron How To

The top-level mac key contains set of options instructing electron-builder on how it should build macOS targets. These options applicable for any macOS target.

  • category String - The application category type, as shown in the Finder via View -> Arrange by Application Category when viewing the Applications directory.

    For example, 'category': 'public.app-category.developer-tools' will set the application category to Developer Tools.

    Valid values are listed in Apple’s documentation.

  • target String | TargetConfiguration - The target package type: list of default, dmg, mas, mas-dev, pkg, 7z, zip, tar.xz, tar.lz, tar.gz, tar.bz2, dir. Defaults to default (dmg and zip for Squirrel.Mac).

  • identity String - The name of certificate to use when signing. Consider using environment variables CSC_LINK or CSC_NAME instead of specifying this option. MAS installer identity is specified in the mas.
  • icon = build/icon.icns String - The path to application icon.
  • entitlements String - The path to entitlements file for signing the app. build/entitlements.mac.plist will be used if exists (it is a recommended way to set). MAS entitlements is specified in the mas.
  • entitlementsInherit String - The path to child entitlements which inherit the security settings for signing frameworks and bundles of a distribution. build/entitlements.mac.inherit.plist will be used if exists (it is a recommended way to set). Otherwise default.

    This option only applies when signing with entitlements provided.

  • provisioningProfile String - The path to the provisioning profile to use when signing, absolute or relative to the app root.

  • bundleVersion String - The CFBundleVersion. Do not use it unless you need to.
  • bundleShortVersion String - The CFBundleShortVersionString. Do not use it unless you need to.
  • darkModeSupport = false Boolean - Whether a dark mode is supported. If your app does have a dark mode, you can make your app follow the system-wide dark mode setting.
  • helperBundleId = ${appBundleIdentifier}.helper String - The bundle identifier to use in the application helper’s plist.
  • type = distribution “distribution” | “development” - Whether to sign app for development or for distribution.
  • extendInfo any - The extra entries for Info.plist.
  • binaries Array<String> - Paths of any extra binaries that need to be signed.
  • minimumSystemVersion String - The minimum version of macOS required for the app to run. Corresponds to LSMinimumSystemVersion.
  • requirements String - Path of requirements file used in signing. Not applicable for MAS.
  • electronLanguages Array<String> | String - The electron locales. By default Electron locales used as is.
  • extraDistFiles Array<String> | String - Extra files to put in archive. Not applicable for tar.*.
  • hardenedRuntime = true Boolean - Whether your app has to be signed with hardened runtime.
  • gatekeeperAssess = false Boolean - Whether to let electron-osx-sign validate the signing or not.

How To Run Electron App

And all common platform-specific options.