Obstacles in notarizing a Kotlin-Multiplatform-based Mac app

I've followed this tutorial: https://github.com/JetBrains/compose-multiplatform/blob/master/tutorials/Signing_and_notarization_on_macOS/README.md

There were 2 problems that I've encountered.

Unable to build chain to self-signed root for signer

The command that failed:

/usr/bin/codesign -vvvv --timestamp --options runtime --force --prefix BUNLDE_PREFIX --sign 'Developer ID Application: Tanin Na Nakorn (S999999X99LE)' /Somepath/Somefile.dylib

Here's an error message:

Warning: unable to build chain to self-signed root for signer "Developer ID Application: Tanin Na Nakorn (S999999X99LE)"

If we read the error very carefully, this means we lack the intermediate and/or root certs.

If you open Keychain Access and look at your Developer ID Application certificate, you'll see the warning "This certificate is not trusted.".

The solution is to install the 4 intermediate certs as specified by this StackOverflow answer: https://stackoverflow.com/a/66083449/710895

This feels really random. Maybe if we were to use XCode, XCode might install these certs automatically. Who knows?

CloudKit query for Something-1.0.0.dmg (2/somethingsomething) failed due to "Record not found"

The command that failed was:

/usr/bin/xcrun stapler staple -v /somepath/Something-1.0.0.dmg

Here's an error message:

CloudKit query for Something-1.0.0.dmg (2/somethingsomething) failed due to "Record not found".
Could not find base64 encoded ticket in response for 2/somethingsomething
The staple and validate action failed! Error 65.

This means there's no record on CloudKit that your app has been notarized. The root cause could be anything like using a wrong cert that isn't "Developer ID Application" or some other random things.

One way to find out more is to look up the notarization error message using notarytool.

You can see the history of notarization using this command: xcrun notarytool history --apple-id APPLE_ID --password PASSWORD --team-id TEAM_ID.

Then, you should see each notarization record. Go to the top, which is the latest one, and get its ID. Then, you can see why it fails with this command: xcrun notarytool log --apple-id APPLE_ID --password PASSWORD --team-id TEAM_ID NOTARIZATION_ID.

In my case, libjnidispatch.jnilib in the resource directory wasn't code-signed. I could either improve my Gradle config to do code-sign when notarizing the app or code-sign it manually.

But I couldn't figure out how to do that with Gradle. Therefore, I've chosen to code-sign it manually for now with this command: /usr/bin/codesign -vvvv --timestamp --options runtime --force --prefix BUNDLE_PREFIX --sign 'Developer ID Application: NAME (TEAM_ID)' PATH_TO/libjnidispatch.jnilib

Subscribe to tanin

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe