Notarizing a plugin in XCode 13.x (macOS Monterey or later)

For XCode 13, which is required for building plugins for Cinema R2024, the process of notarizing a plugin has been made significantly easier. If you haven't notarized a plugin before, first see the page dealing with earlier versions of Xcode here.

In those earlier versions, a number of steps were required for each notarization and the process used the altool commandline tool. This is deprecated in XCode 13 and a new tool. 'notarytool' is used instead.

Apple have stated that the notary service will not support the use of altool after November 1st 2023, and to use notarytool instead.

These are some notes on my experience in using notarytool. I've given them here in case anyone should find them useful when starting to use it. Please note that I make no guarantee that this will always work with your plugins - it's a learning experience for me too!

1. What you will need

As with the earlier process, you need:

  1. a (paid) Apple Developer account
  2. a Developer ID Application certificate
  3. an app-specific password
  4. a Team ID

If you have notarized a plugin before, you already have the first three and you don't need to get the Developer ID or app password again. If you don't have them, follow the procedure in steps 1, 2, and 3b on the older page.

Once you have finished points 1-3 above, you will already have the Team ID, but you probably just don't know it. There are two ways to get it. If you have built a plugin and signed it following step 4a on the older page, you will see your developer ID certificate in the 'Code Signing Identity' line. This will have the name of your developer ID followed by a string of 10 letters and digits. That string is the Team ID.

The alternative is to use this command in Terminal:

security find-identity -p basic -v

This will list the ID certificates on your machine. On mine, there was only one so the result of that command looked like this:

1) [very long string of letters and numbers] "Developer ID Application: Stephen Pedler (A1B2C3D4E5)"
1 valid identities found

That string 'A1B2C3D4E5' is the Team ID for this Developer ID (that's not a genuine ID, but it will look like that).

Remember, you only have to do this once so be sure to make a note of the Team ID.

2. Add the credentials to your keychain

You now have all the credentials required to use notarytool to notarize your plugins. It's really convenient to store them in your keychain, and you do that with the notarytool like this:

xcrun notarytool store-credentials --apple-id "your Apple ID" --team-id "the Team ID you found in step 1"

This command outputs this result:

Note that it asks for two pieces of information. The first is a profile name, which can be anything; I chose my website's domain name, which is echoed to the terminal (''). You will certainly want to choose something different. Then it wants the app-specific password you already generated for your Apple ID, and it doesn't echo this. Finally, it attempts to validate these credentials and assuming it does so successfully, it saves them to the keychain. Once that is done, you will never need to do steps 1 and 2 again, because you can just get the credentials for notarizing from the keychain.

Note: that profile name is important, so make a note of it. You will need it when submitting the plugin to be notarized and when querying any errors.

3. Notarizing your plugin

First, make sure you have signed the plugin as shown in step 4 of the older page. There's nothing different to do from the steps shown there. Then build the plugin in the version to be released and create a .zip file of it ready to be notarized. Doing the actual notarizing is very simple. For testing the process I used one of my plugins called 'NudgeIt' and the command line looked like this:

xcrun notarytool submit "/Users/steve/Documents/C4D_Plugins/NotarizeR2024/NudgeItR2024/" --keychain-profile "" --wait

Of course, the path to the file and the keychain profile will vary.

What you get in return is this:

This gives you a 'submission ID'. You will need this if you ever need to query the result of the process.

Very importantly, that single line saying 'status: Accepted' is the only indication you get that the plugin has been notarized. Unlike the previous method, the notary service does NOT send an email with the result in it.

The beauty of this system is that is so much faster and simpler than previously. You only have to get the required credentials once and it's much easier to notarize any plugin after that. Adding the credentials to your keychain makes it easy to notarize any number of plugins - just zip up the plugin then run notarytool to submit the .zip file.

3a. The --wait switch

This is shown in the command line above, but it is optional. If you don't include it the notary service won't send back the result. So how do you find it out? You can use notarytool with the info verb (instead of submit) like so:

xcrun notarytool info [your submission ID] --keychain-profile "[your profile name]"

Note that you need the submission ID the service returned when the file was submitted. The return will look like this:

4. Errors

What happens if the notarizing fails? In that case, you get the same return message but this time you get the line 'status: Invalid'. That's it. No explanation of what the problem was. If you use notarytool with the info verb as above, you just get the same 'invalid' response. Instead, use the 'log' verb:

xcrun notarytool log [your submission ID] --keychain-profile "[your profile name]"

This will give you some more details, for example like this:

You can see that you get the same error report twice, if building universal binaries.

Now, the problem here is this. Suppose when signing the plugin in XCode you did everything except (for example) setting 'Enable Hardened Runtime' to 'Yes'. You even included the "--timestamp" switch, so you'd expect the notary service to tell you what you needed to put right. As far as I can see, it doesn't. I've tried several deliberate errors and the only report I've ever received is for a missing timestamp, and even if you then correct the actual error in Xcode so that everything should be fine, you still get the same error response. The only solution then is to make sure everything is correct in the code signing in XCode, then manually sign the plugin as shown in step 7 on the older page. Then it will (should) work.

Page last updated September 30th 2023