How I notarized my desktop AIR project for MacOS AppStore

This took me some time so maybe good to share.

Stuff needed:

  • XCode command line tools
  • apple developer account
  • app configured in the apple developer / itunesconnect account, bundle id com.example.this
  • Developer ID Application certificate type
  • API key for apple developer generated and downloaded (created dir ~/.private_keys and moved downloaded key there)

Steps:

  • Added<architecture>64</architecture> and <id>com.example.this</id> to this.xml in Flash Builder project src, added -swf-version=40 to compiler arguments
  • Exported Release build via Signed Application with captive runtime
  • Once this.app was created Edited this.app/Contents/info.plist and this.app/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/Info.plist to include:
  <key>UseHardenedRuntime</key>
  <true/>
    <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.disable-executable-page-protection</key>
    <true/>
  • Opened a terminal to signed everything relevant in it
  codesign --timestamp --deep -f -v -s "Developer ID Application: ACME inc (1WT4B03F67)" this.app/Contents/Frameworks/Adobe\ AIR.framework/Versions/1.0/Resources/Flash\ Player.plugin/Contents/MacOS/FlashPlayer-10.6
  codesign --timestamp --deep -f -v -s "Developer ID Application: ACME inc (1WT4B03F67)" --options runtime  this.app/Contents/Frameworks/Adobe\ AIR.framework/Versions/1.0/Resources/A2712Enabler
  codesign --timestamp --deep -f -v -s "Developer ID Application: ACME inc (1WT4B03F67)" this.app/Contents/Frameworks/Adobe\ AIR.framework/Versions/1.0/Resources/WebKit.dylib
  codesign --timestamp --deep -f -v -s "Developer ID Application: ACME inc (1WT4B03F67)" this.app/Contents/Frameworks/Adobe\ AIR.framework/Versions/1.0/Adobe\ AIR
  codesign --timestamp --deep -f -v -s "Developer ID Application: ACME inc (1WT4B03F67)" this.app/Contents/Frameworks/Adobe\ AIR.framework/Versions/1.0/Adobe\ AIR_64
  codesign --timestamp --deep -f -v -s "Developer ID Application: ACME inc (1WT4B03F67)" --options runtime this.app/Contents/MacOS/this
  • Once signed, compressed this.app to this.zip
  • Submitted archive to notarization
  	xcrun altool --notarize-app --primary-bundle-id "com.example.this" -t osx --apiIssuer 11a1aa1a-11a1-11a1-a111-111a1a11a1a1 --apiKey CFEBA4444A --file this.zip
  • Collected the status of the RequestUUID returned
  	xcrun altool --notarization-history 0 --apiIssuer 11a1aa1a-11a1-11a1-a111-111a1a11a1a1 --apiKey CFEBA4444A
  • Inspected the notarization info
  	xcrun altool --notarization-info 22b2bb2b-22b2-22b2-b222-222b2b22b2a2 --apiIssuer 11a1aa1a-11a1-11a1-a111-111a1a11a1a1 --apiKey CFEBA4444A

got Status Message: Package Approved
prior cases I was inspecting LogFileURL: returned in notarization info to repair this.app package

Maybe this.app will be approved and in the mac osx app store soon so my Catalina users can work again.

Hope this helps to you too.

8 Likes

I don’t mean to rain on your parade but notarization is for distributing apps yourself. You don’t notarize a Mac app for the AppStore

https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution

Beginning in macOS 10.14.5, software signed with a new Developer ID certificate and all new or updated kernel extensions must be notarized to run. Beginning in macOS 10.15, all software built after June 1, 2019, and distributed with Developer ID must be notarized. However, you aren’t required to notarize software that you distribute through the Mac App Store because the App Store submission process already includes equivalent security checks.

Yes I learned that too. You can’t get the air app into the app store. So the only thing you can do is to notarize it so the people can install the pkg. You’re right the title of the post is not good, shouldn’t have AppStore in it…

Thanks for this post, you saved my day! I also created a .sh bash script to run all the codesigning at once. Cheers!

hi I tried all the points you mentioned. when I code size your last line I get
/SM.app/Contents/MacOS/Die Seemannschaft: unsealed contents present in the bundle root

What am I doing wrong.
please help stuck here

Hi, @Benjamin_Povirk you made it super simple, I got the process working last September but then yesterday made an update and got a bunch of errors related to items not signed, or timestamped. I see the items you listed and they were all there! If I had read your post, it would’ve been simpler than the torture I endured.

@Menard1965 I just went through this process and got a similar error – the problem I had was my files were in Dropbox and I had forgotten to pause it while compiling, so some extra files got added into the .app file. For example, there was a file like “something” and then “something [Jonathan’s copy…]” got added.

So perhaps extra files got into the .app file. You can cd into the .app file and then start looking around for files that seem out of place, it was very obvious in my case. I just removed those files, and the problem with the “unsealed contents” went away. Look particularly at the folder the error is telling you – i.e., /SM.app/Contents/MacOS/Die Seemannschaft. If the extra files are not obvious you may have to make a copy of your app for safekeeping and then try deleting some files until you can clear the error.

Would you mind sharing the script?

I thought my problems were over last night but I woke up this morning to my dmg and app not working (I would open it and it would close immediately, with an error). It had been notarized and everything!

Mind you, I was still using AIR 32, so my results may be different. So I walked through my steps again, but also paying attention to what is in this thread. I am on Catalina 10.15.5.

After several hours, I got it all worked out. Perhaps others can benefit from seeing my exact steps, so here goes:

– Compiled my app with ADT
../AdobeAIRSDK/AdobeAIRSDK-32/bin/adt -package -storetype pkcs12 -keystore myCert.p12 -tsa http://sha256timestamp.ws.symantec.com/sha256/timestamp -target bundle "SimsUshare_v2.app" SUSFreeWinMac-app.xml -C . SUSFreeWinMac.swf libs/ examples/ icons/ piccache/ assets/

– entered my password

– fixing links in the .app
cd “SimsUshare_v2.app/Contents/Frameworks/Adobe AIR.framework”
rm “Adobe AIR”
ln -s Versions/Current/Adobe\ AIR “Adobe AIR”
ln -s Versions/Current/Adobe\ AIR_64 “Adobe AIR_64”

Edited this.app/Contents/Info.plist and this.app/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/Info.plist to include:

  <key>UseHardenedRuntime</key>
  <true/>
    <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.disable-executable-page-protection</key>
    <true/>

– Removing stuff that would cause problems

rm -f "./SimsUshare_v2.app/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/WebKit.dylib"
rm -f "./SimsUshare_v2.app/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/Adobe AIR.vch"
rm -fr "./SimsUshare_v2.app/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/__MACOSX"

– removing extended resources (Apple calls it detritus)
xattr -cr SimsUshare_v2.app

– resetting info in Info.plist

/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString \"2.9.4\"" "/Users/jonathankaye/Dropbox/SimsUshare Builds/mac/SimsUshare 2.9.4/SimsUshare_v2.app/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleGetInfoString \"${VERSION}, © 2020 Equipment Simulations LLC. All rights reserved.\"" "/Users/jonathankaye/Dropbox/SimsUshare Builds/mac/SimsUshare 2.9.4/SimsUshare_v2.app/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Add :LSApplicationCategoryType string public.app-category.business" "/Users/jonathankaye/Dropbox/SimsUshare Builds/mac/SimsUshare 2.9.4/SimsUshare_v2.app/Contents/Info.plist"

– Code-signing the pieces

codesign --timestamp --deep -f -v -s "Developer ID Application: Equipment Simulations LLC" "/Users/jonathankaye/Dropbox/SimsUshare Builds/mac/SimsUshare 2.9.4/SimsUshare_v2.app/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/Flash Player.plugin/Contents/MacOS/FlashPlayer-10.6"
codesign --timestamp --deep -f -v -s "Developer ID Application: Equipment Simulations LLC" --options runtime  "/Users/jonathankaye/Dropbox/SimsUshare Builds/mac/SimsUshare 2.9.4/SimsUshare_v2.app/Contents/Frameworks/Adobe AIR.framework/Versions/1.0/Resources/A2712Enabler"
codesign --timestamp --deep -f -v -s "Developer ID Application: Equipment Simulations LLC" "/Users/jonathankaye/Dropbox/SimsUshare Builds/mac/SimsUshare 2.9.4/SimsUshare_v2.app/Contents/Frameworks/Adobe AIR.framework"

– signing the app
codesign --timestamp --deep -f -v --options runtime -s "Developer ID Application: Equipment Simulations LLC" --entitlements "/Users/jonathankaye/Dropbox/SimsUshare Builds/mac/SimsUshare 2.9.4/entitlements.plist" "/Users/jonathankaye/Dropbox/SimsUshare Builds/mac/SimsUshare 2.9.4/SimsUshare_v2.app"

– I tested the app, all worked well still

– I made the DMG with DropDMG

– start notarizing

xcrun altool --type osx --file SimsUshare_v2.dmg --primary-bundle-id com.simsushare.SUSMobileDesktop --notarize-app --username "u@eqsim.com" --password “**”

– At first with original password from yesterday, failed with “unable to create authentication session”, so I created a new app-specific password

xcrun altool --type osx --file SimsUshare_v2.dmg --primary-bundle-id com.simsushare.SUSMobileDesktop --notarize-app --username "u@eqsim.com" --password “*****”

No errors uploading 'SimsUshare_v2.dmg'.
RequestUUID = 68ca4ac1-*****-77cf1166****

– then I typed

xcrun altool --notarization-info 68ca4ac1-*****-77cf1166**** --username "u@eqsim.com" --password "**"

No errors getting notarization info.

  Date: 2020-06-30 16:12:47 +0000
  Hash: 3ab1a2e522b3055------ece6c782b69fc

LogFileURL: https://osxapps-ssl.itunes.apple.com/itunes-assets/Enigma113/v4/d8/60/f2/d860f2dddddddKl%2BzhosxnLqynlmbvNUUpIcc32mVFYkQ%3D
RequestUUID: 68ca4ac1-*****-77cf1166****
Status: success
Status Code: 0
Status Message: Package Approved


Then I did the stapling:

xcrun stapler staple -v SimsUshare_v2.dmg

Processing: /Users/jonathankaye/Dropbox/SimsUshare Builds/mac/SimsUshare 2.9.4/SimsUshare_v2.dmg
Properties are {
    NSURLIsDirectoryKey = 0;
    NSURLIsPackageKey = 0;
    NSURLIsSymbolicLinkKey = 0;
    NSURLLocalizedTypeDescriptionKey = "Disk Image";
    NSURLTypeIdentifierKey = "com.apple.disk-image-udif";
    "_NSURLIsApplicationKey" = 0;

…lots of stuff ending with
The staple and validate action worked!

all good, but my guess if your earlier struggle were due to using the command-line itself

anyway, few comments

see:

Customizing the Notarization Workflow
Notarize your app from the command line to handle special distribution cases.

Add the username and password options to supply your App Store Connect credentials. Because App Store Connect now requires two-factor authentication (2FA) on all accounts, you must create an app-specific password for altool , as described in Using app-specific passwords.

To avoid including your password as cleartext in a script, you can provide a reference to a keychain item, as shown in the previous example. This assumes the keychain holds a keychain item named AC_PASSWORD with an account value matching the username AC_USERNAME .

and also this part

Check the Status of Your Request

After uploading your app, the notarization process typically takes less than an hour. When the process completes, you receive an email indicating the outcome. Additionally, you can use altool with the notarization-history option to inspect the status of all of your notarization requests:

$ xcrun altool --notarization-history 0 -u "AC_USERNAME" -p "@keychain:AC_PASSWORD"

the point is that the notarization is not necessarily instantaneous

your first call to

might not work the first time, and so you need to go in a loop a of wait and check till it is valid, something not easily done on the command-line with Bash

and the final part also important to check

Avoid Long Notarization Response Times and Size Limits

Notarization completes for most software within 5 minutes, and for 98% of software within 15 minutes. However, notarization can take longer under certain conditions. Help to avoid long response times by following a few rules:

  • Minimize the total number of files, even when the individual files are small.

  • Don’t save non-executable files in places that require code signatures, like MyApp.app/Content/MacOS/ . Instead, save these files to a directory that doesn’t require a code signature, like MyApp.app/Contents/Resources/ .

  • Don’t submit corrupted disk images. You can verify the integrity of a disk image by running the hdiutil utility:

    $ hdiutil verify <image>
    
  • Avoid heavily compressed disk images.

  • Avoid huge, non-executable data files, especially when they change often.

  • Limit notarizations to 75 per day.

The notarization service restricts uploads to 50 GB. If an upload exceeds the limit, try to exclude non-executable data from notarization. For example, if you use an installer package, you could move all your non-executable data into a folder next to a notarized installer package. Put both the data and the notarized installer package into a single disk image, and ship the disk image without notarization.


Also I disagree on a couple of stuff

for ex, removing WebKit.dylib is only if you want to publish the app on the mac App Store,
if you distribute the app from your own web site you can keep it, especially if you want to use HTMLLoader.

and maybe the DMG part, yeah sure you can use DMG if you want but you can use ZIP and PKG too, and all of those can be done on the command-line too

but I get it, some GUI tool can make things easier, so here one
Packages, to build PKG files

Re: removing WebKit, I didn’t realize that, in the flurry of activity when I did this last year, WebKit was flagged in the notarization process and I thought Apple was prohibiting it outright (because Apple can, unfortunately).

Re: DMG, my audience is not tech savvy so I am concerned they may not know what to do with the individual files as a ZIP or PKG. Also, DropDMG is awesome and simple. Thanks for the suggestions.