question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

MAS code signing and distribution guide request

See original GitHub issue

Hello!

Thank you very much for nw.js!

Me and my colleagues are currently trying to prepare our nwjs app for Mac App Store distribution. But there is a lack of information on how to do it properly.

We use NWJS 0.27.1 on Mac OS 10.13.2. The documentation suggests to use MAS helper script, but it seems to be designed for nwjs 0.19.5, whereas our project uses latest nwjs features such as importNWBin.

Still, we’ve tried to sign our app with that script with entitlements relevant to our app features. Unfortunately the application signed with build_mas.py silently crashes upon start regardless of signing identity set in the configuration file. Here is a crash log that was captured via OS X Console app: app-signed-via-build_mas-crash-log.txt

We have tested build_mas.py with these kinds of identity:

  • 3rd Party Mac Developer Application
  • Developer ID Application
  • Mac Developer

All the necessary certificates and provision profiles were properly installed on the system that has been used for a code signing.

We have also tried signing our product with the following self-made script:

#!/bin/sh

APP_IDENTITY="Mac Developer: Our Identity (...)"
ENTITLEMENTS_CHILD="entitlements-child.plist"
ENTITLEMENTS_PARENT="entitlements-parent.plist"
APP="Our App Name.app"

sign () {
    OBJECT=$1
    ENTITLEMENTS=$2

    codesign --force --verbose --verify --sign "$APP_IDENTITY" --entitlements "$ENTITLEMENTS" --deep "$OBJECT"
    codesign --verify --deep --strict --verbose=2 "$OBJECT"
}

sign "$APP/Contents/Versions/63.0.3239.84/nwjs Framework.framework/libnode.dylib" "$ENTITLEMENTS_CHILD"
sign "$APP/Contents/Versions/63.0.3239.84/nwjs Framework.framework/Helpers/crashpad_handler" "$ENTITLEMENTS_CHILD"
sign "$APP/Contents/Versions/63.0.3239.84/nwjs Framework.framework/XPCServices/AlertNotificationService.xpc" "$ENTITLEMENTS_CHILD"
sign "$APP/Contents/Versions/63.0.3239.84/nwjs Framework.framework/nwjs Framework" "$ENTITLEMENTS_CHILD"
# sign "$APP/Contents/Versions/63.0.3239.84/nwjs Framework.framework" "$ENTITLEMENTS_CHILD"

sign "$APP/Contents/Versions/63.0.3239.84/nwjs Helper.app" "$ENTITLEMENTS_CHILD"
sign "$APP/Contents/Versions/63.0.3239.84/libffmpeg.dylib" "$ENTITLEMENTS_CHILD"

sign "$APP" "$ENTITLEMENTS_PARENT"

The instructions listed above work correctly and the codesign validation shows valid on disk / satisfies its Designated Requirement status for every resource it is applied to (except nwjs Framework.framework that will be mentioned further). However the application signed with this script crashes in the same way as described earlier. This time the crash log differs from the one attached above, but it also has a lot in common: app-signed-for-development-crash-log.txt

It is also worth to note that both of the above scripts (build_mas.py and the one we created ourselves) have displayed a following error after the attempt to sign nwjs Framework.framework

Our App Name.app/Contents/Versions/63.0.3239.84/nwjs Framework.framework: unsealed contents present in the root directory of an embedded framework

I suppose that the reason of this error is that the nwjs Framework.framework itself consists of a large number of resources each of which should be signed on it’s own as described in the apple documentation https://developer.apple.com/library/content/documentation/Security/Conceptual/CodeSigningGuide/Procedures/Procedures.html.

Additionally we have tried to manually sync our app’s bundle identifier and display name with PlistBuddy utility but it doesn’t seem to solve our problem as well.

BUNDLE_ID="our.app.bundle.id"
APP_NAME="Our App Name"

sed -i '' "s#(CFBundleDisplayName[^\"]\")[^\"](\")#\1$APP_NAME\2#g" "$APP/Contents/Resources/en.lproj/InfoPlist.strings"

/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $BUNDLE_ID" "$APP/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $APP_NAME" "$APP/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $BUNDLE_ID.helper" "$NWJS_HELPER/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName $APP_NAME Helper" "$NWJS_HELPER/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :com.apple.security.application-groups $BUNDLE_ID" "$ENTITLEMENTS_PARENT"

Is there a way to make it work? We would really appreciate if someone shared some experience or advice on how to do MAS code signing properly. We will be happy for any help. Thanks in advance!

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:4
  • Comments:31 (1 by maintainers)

github_iconTop GitHub Comments

3reactions
tankakatancommented, Dec 16, 2017

Good news everyone!

The reason of the crash was the usage of the apple sandbox entitlement. If it is set to false app starts normally.

However it would be nice to find out the problem that leads our app to crash while running in the sandbox. The log attached to the issue says much about sandbox errors. So any ideas on how to solve them are welcome!

1reaction
zkrigecommented, Feb 14, 2020

@zkrige To fix the collision, I followed the Mac instructions in https://nwjs.readthedocs.io/en/nw28/For Users/Package and Distribute/#platform-specific-steps (They are out of date. The helpers are now in a Helpers directory.) So, I renamed CFBundleDisplayName and CFBundleExecutable in each plist file and while I was there I parsed the name and got the part in the parenthesis and added it to the CFBundleIdentifier. For example: io.nwjs.nwjs.helper for nwjs Helper.app and io.nwjs.nwjs.helper.gui for nwjs Helper (GUI).app Seems to have fixed the collision for me

Thank You - I figured this out and managed to do the same. The only problem remaining is the sandbox issue

Read more comments on GitHub >

github_iconTop Results From Across the Web

Signing a Mac Product For Distribution - Apple Developer
Apps and non-apps can be distributed outside of the Mac App Store using Developer ID signing.
Read more >
Code Signing macOS Applications | Tauri Apps
This guide provides information on code signing and notarization for macOS applications.
Read more >
Generating code signing files
To get a certificate, you need to generate a Certificate Signing Request ... To setup a distribution Provisioning Profile, go ahead with the...
Read more >
Code Signing Guide for Teams
Next, create a new private key and certificate for each environment, such as “Distribution” and “Development”. Then store these private keys and certificates...
Read more >
Provision a .NET MAUI iOS app for app store distribution
To create a distribution certificate, you'll first need to create a certificate signing request (CSR) in Keychain Access on a Mac:.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found