"Invalid Provisioning Profile" Error on TestFlight

I have a Safari Extension deployed to test flight built and deployed using CLI tools in Azure Devops. It appears to be building, signing, and deploying properly. But when users try to install on TestFlight, they see an error saying something about an invalid provisioning profile. This seems to just be on the "installer" portion of the app. The extension shows up in safari settings and is otherwise useable. The users just aren't seeing the splash screen that instructs them to go to Safari Settings.

I'm not really sure what's wrong here. This is what my build pipeline looks like

      - task: Bash@3
        displayName: "Build export.plist file"
        inputs:
          targetType: 'inline'
          script:
            /usr/libexec/PlistBuddy -c "Add :method string mac-application" $(Pipeline.Workspace)/export.plist &&
            /usr/libexec/PlistBuddy -c "Add :provisioningProfiles dict" $(Pipeline.Workspace)/export.plist &&
            /usr/libexec/PlistBuddy -c "Add :provisioningProfiles:$(APP_IDENTIFIER) string $(InstallDistProvisioningProfile.provisioningProfileUuid)" $(Pipeline.Workspace)/export.plist &&
            /usr/libexec/PlistBuddy -c "Add :signingCertificate string '$(InstallDistCerts.signingIdentity)'" $(Pipeline.Workspace)/export.plist &&
            /usr/libexec/PlistBuddy -c "Add :signingStyle string manual" $(Pipeline.Workspace)/export.plist &&
            /usr/libexec/PlistBuddy -c "Add :teamID string $(APPLE_TEAM_ID)" $(Pipeline.Workspace)/export.plist &&
            /usr/libexec/PlistBuddy -c "Add :iCloudContainerEnvironment string Production" $(Pipeline.Workspace)/export.plist &&
            /usr/libexec/PlistBuddy -c "Add :stripSwiftSymbols bool true" $(Pipeline.Workspace)/export.plist &&
            /usr/libexec/PlistBuddy -c "Add :compileBitcode bool false" $(Pipeline.Workspace)/export.plist

      - task: Xcode@5
        displayName: "Build Safari Extension"
        inputs:
          action: "archive"
          sdk: "macosx"
          packageApp: true
          xcodeVersion: "15"
          args: "-verbose CODE_SIGNING_REQUIRED=Yes CODE_SIGNING_ALLOWED=Yes"
          exportOptions: "plist"
          exportOptionsPlist: '$(Pipeline.Workspace)/export.plist'
          exportMethod: "mac-application"
          archivePath: '$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.xcarchive'
          signingOption: "default"

      - script: |
          xcodebuild -exportArchive \
          -archivePath $(Build.ArtifactStagingDirectory)/SafariDesktopExtension.xcarchive \
          -exportPath $(Build.ArtifactStagingDirectory) \
          -exportOptionsPlist $(Pipeline.Workspace)/export.plist
        displayName: 'Export Distribution-signed App'

      - task: DownloadSecureFile@1
        displayName: "Download Provisioning Profile"
        name: downloadProvisioningProfile
        inputs:
          secureFile: $(PROVISIONING_PROFILE_DIST)

      - script: |
          cp "$(downloadProvisioningProfile.secureFilePath)" "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.app/Contents/embedded.provisionprofile"
        displayName: "Embed provisioning profile in Top-Level Executable"

      - script: |
          cp "$(downloadProvisioningProfile.secureFilePath)" "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.app/Contents/PlugIns/SafariDesktopExtension Extension.appex/Contents/embedded.provisionprofile"
        displayName: "Embed provisioning profile in Extension"

      - script: |
          codesign --deep --force --verify --verbose --sign "$(InstallDistCerts.signingIdentity)" --entitlements "$(rootFolder)/safari/SafariDesktopExtension/SafariDesktopExtension/SafariDesktopExtension.entitlements" $(Build.ArtifactStagingDirectory)/SafariDesktopExtension.app
        displayName: "Codesign"

      - task: Bash@3
        displayName: "Package Application"
        inputs:
          targetType: "inline"
          script: |
            productbuild --sign "$(InstallInstallerCert.signingIdentity)" --component "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.app" /Applications "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.pkg"

I'm sure there's a bit of garbage here as I'm new to developing in the apple ecosystem. But it appears to work and the resulting .pkg can be submitted successfully.

Effectively, that's building an archive using a plist for export options, exporting the archive for distribution, copying the distribution provisioning profile for the top-level executable (the one that's not working) and the extension itself, code signing, and packaging using the installer cert.

The provisioning profile (attached to a Mac distribution certificate) mentioned has the correct application identifier and matches the entitlements.

I'm not really sure what's going on here and the generic "invalid provisioning profile" error isn't helping. Any help would be appreciated. I'd also love to know if this could hold up a release.

Answered by pmiller22 in 803409022

I was able to resolve this by

  • dropping use of the xcode@5 task and use xcodebuild directly
  • dropping xcodebuild -exportArchive and handling that myself by manually dropping in my provisioning profiles, manually signing with codesign, and packaging with productBuild

At first, it seemed that I was using -exportArchive wrong having selected Mac-Application instead of app-connect as the export method. Fixing that worked well enough after I included my installer provisioning profile in the plist, however I ran into issues with the distribution provisioning profiles here as the embedded application (safari extension) had a different bundle-id than the top-level application. This required that I do all of that manually (though I bet resolve itself if I update the bundle identifier to match, but I'm short on time and I'm going to stick with this for now unless it causes me problems...)

For posterities sake, the working pipeline is:

      - task: InstallAppleCertificate@2
        displayName: "Install Developer Certificate" 
        name: InstallAppleCertificate
        inputs:
          certSecureFile: $(APPLE_DEV_CERT)
          certPwd: $(APPLE_DEV_CERT_PASSWORD)

      - task: InstallAppleCertificate@2
        displayName:  "Install Distribution Certificate"
        name: InstallDistCerts
        inputs:
          certSecureFile: $(APPLE_DIST_CERT)
          certPwd: $(APPLE_DIST_CERT_PASSWORD)

      - task: InstallAppleProvisioningProfile@1
        displayName: "Install Distribution Provisioning Profile"
        name: InstallDistProvisioningProfile
        inputs:
          provProfileSecureFile: $(PROVISIONING_PROFILE_DIST)

      - task: InstallAppleCertificate@2
        displayName: "Install Installer Certificate"
        name: InstallInstallerCert
        inputs:
          certSecureFile: $(APPLE_INSTALLER_CERT)
          certPwd: $(APPLE_INSTALLER_CERT_PASSWORD)

      - task: InstallAppleProvisioningProfile@1
        displayName: "Install Extension Distribution Provisioning Profile"
        name: InstallExtDistProvisioningProfile
        inputs:
          provProfileSecureFile: $(EXTENSION_PROVISIONING_PROFILE)

      - task: Bash@3
        displayName: "Update Safari Bundle Version"
        inputs:
          workingDirectory: "browser-extensions"
          filePath: "browser-extensions/update-pbxproj-version.sh"

      - template: build-extension.yml

      - script: |
          sudo xcodebuild -project "browser-extensions/chrome-v2/safari/SafariDesktopExtension/SafariDesktopExtension.xcodeproj" \
            -scheme SafariDesktopExtension \
            -configuration Release \
            archive \
            -archivePath '$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.xcarchive' \
            CODE_SIGNING_REQUIRED=NO \
            CODE_SIGNING_ALLOWED=NO
        displayName: 'Archive Xcode Project'

      - task: DownloadSecureFile@1
        displayName: "Download Provisioning Profile"
        name: downloadProvisioningProfile
        inputs:
          secureFile: $(PROVISIONING_PROFILE_DIST)

      - task: DownloadSecureFile@1
        displayName: "Download Provisioning Profile"
        name: downloadExtensionProvisioningProfile
        inputs:
          secureFile: $(EXTENSION_PROVISIONING_PROFILE)

      - script: |
          sudo cp "$(downloadProvisioningProfile.secureFilePath)" "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.xcarchive/Products/Applications/SafariDesktopExtension.app/Contents/embedded.provisionprofile"
        displayName: "Embed provisioning profile in Top-Level Executable"

      - script: |
          sudo cp "$(downloadExtensionProvisioningProfile.secureFilePath)" "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.xcarchive/Products/Applications/SafariDesktopExtension.app/Contents/PlugIns/SafariDesktopExtension Extension.appex/Contents/embedded.provisionprofile"
        displayName: "Embed provisioning profile in Extension"

      - script: |
          # Sign the nested app extension
          sudo codesign --verbose --sign "$(InstallDistCerts.signingIdentity)" \
            --entitlements "$(rootFolder)/safari/SafariDesktopExtension/SafariDesktopExtension Extension/SafariDesktopExtension_Extension.entitlements" \
            "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.xcarchive/Products/Applications/SafariDesktopExtension.app/Contents/PlugIns/SafariDesktopExtension Extension.appex"

          # Sign additional components if necessary (e.g., frameworks, helper apps)
          find "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.xcarchive/Products/Applications/SafariDesktopExtension.app/Contents/Frameworks" -type f -name "*.dylib" -or -name "*.framework" | while read component; do
              sudo codesign --force --verbose --sign "$(InstallDistCerts.signingIdentity)" "$component"
          done

          # Sign the main app
          sudo codesign --force --verbose --sign "$(InstallDistCerts.signingIdentity)" \
            --entitlements "$(rootFolder)/safari/SafariDesktopExtension/SafariDesktopExtension/SafariDesktopExtension.entitlements" \
            "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.xcarchive/Products/Applications/SafariDesktopExtension.app"
        displayName: "Codesign"

      - task: Bash@3
        displayName: "Package Application"
        inputs:
          targetType: "inline"
          script: |
            productbuild --sign "$(InstallInstallerCert.signingIdentity)" --component "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.xcarchive/Products/Applications/SafariDesktopExtension.app" /Applications "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.pkg"

      - task: PublishBuildArtifacts@1
        inputs:
          PathToPublish: "$(Build.ArtifactStagingDirectory)"
          ArtifactName: "SafariDesktopExtension"
        displayName: "Publish Desktop Extension Artifact"

If you submit your app from the Xcode organiser, does it have the same problem?

This is a useful test because:

  • If it works from the organiser, then you can compare its submission to your submission to see what’s different.

  • If it doesn’t work, you’ve eliminated your custom CI system from the equation.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer

I was able to resolve this by

  • dropping use of the xcode@5 task and use xcodebuild directly
  • dropping xcodebuild -exportArchive and handling that myself by manually dropping in my provisioning profiles, manually signing with codesign, and packaging with productBuild

At first, it seemed that I was using -exportArchive wrong having selected Mac-Application instead of app-connect as the export method. Fixing that worked well enough after I included my installer provisioning profile in the plist, however I ran into issues with the distribution provisioning profiles here as the embedded application (safari extension) had a different bundle-id than the top-level application. This required that I do all of that manually (though I bet resolve itself if I update the bundle identifier to match, but I'm short on time and I'm going to stick with this for now unless it causes me problems...)

For posterities sake, the working pipeline is:

      - task: InstallAppleCertificate@2
        displayName: "Install Developer Certificate" 
        name: InstallAppleCertificate
        inputs:
          certSecureFile: $(APPLE_DEV_CERT)
          certPwd: $(APPLE_DEV_CERT_PASSWORD)

      - task: InstallAppleCertificate@2
        displayName:  "Install Distribution Certificate"
        name: InstallDistCerts
        inputs:
          certSecureFile: $(APPLE_DIST_CERT)
          certPwd: $(APPLE_DIST_CERT_PASSWORD)

      - task: InstallAppleProvisioningProfile@1
        displayName: "Install Distribution Provisioning Profile"
        name: InstallDistProvisioningProfile
        inputs:
          provProfileSecureFile: $(PROVISIONING_PROFILE_DIST)

      - task: InstallAppleCertificate@2
        displayName: "Install Installer Certificate"
        name: InstallInstallerCert
        inputs:
          certSecureFile: $(APPLE_INSTALLER_CERT)
          certPwd: $(APPLE_INSTALLER_CERT_PASSWORD)

      - task: InstallAppleProvisioningProfile@1
        displayName: "Install Extension Distribution Provisioning Profile"
        name: InstallExtDistProvisioningProfile
        inputs:
          provProfileSecureFile: $(EXTENSION_PROVISIONING_PROFILE)

      - task: Bash@3
        displayName: "Update Safari Bundle Version"
        inputs:
          workingDirectory: "browser-extensions"
          filePath: "browser-extensions/update-pbxproj-version.sh"

      - template: build-extension.yml

      - script: |
          sudo xcodebuild -project "browser-extensions/chrome-v2/safari/SafariDesktopExtension/SafariDesktopExtension.xcodeproj" \
            -scheme SafariDesktopExtension \
            -configuration Release \
            archive \
            -archivePath '$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.xcarchive' \
            CODE_SIGNING_REQUIRED=NO \
            CODE_SIGNING_ALLOWED=NO
        displayName: 'Archive Xcode Project'

      - task: DownloadSecureFile@1
        displayName: "Download Provisioning Profile"
        name: downloadProvisioningProfile
        inputs:
          secureFile: $(PROVISIONING_PROFILE_DIST)

      - task: DownloadSecureFile@1
        displayName: "Download Provisioning Profile"
        name: downloadExtensionProvisioningProfile
        inputs:
          secureFile: $(EXTENSION_PROVISIONING_PROFILE)

      - script: |
          sudo cp "$(downloadProvisioningProfile.secureFilePath)" "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.xcarchive/Products/Applications/SafariDesktopExtension.app/Contents/embedded.provisionprofile"
        displayName: "Embed provisioning profile in Top-Level Executable"

      - script: |
          sudo cp "$(downloadExtensionProvisioningProfile.secureFilePath)" "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.xcarchive/Products/Applications/SafariDesktopExtension.app/Contents/PlugIns/SafariDesktopExtension Extension.appex/Contents/embedded.provisionprofile"
        displayName: "Embed provisioning profile in Extension"

      - script: |
          # Sign the nested app extension
          sudo codesign --verbose --sign "$(InstallDistCerts.signingIdentity)" \
            --entitlements "$(rootFolder)/safari/SafariDesktopExtension/SafariDesktopExtension Extension/SafariDesktopExtension_Extension.entitlements" \
            "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.xcarchive/Products/Applications/SafariDesktopExtension.app/Contents/PlugIns/SafariDesktopExtension Extension.appex"

          # Sign additional components if necessary (e.g., frameworks, helper apps)
          find "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.xcarchive/Products/Applications/SafariDesktopExtension.app/Contents/Frameworks" -type f -name "*.dylib" -or -name "*.framework" | while read component; do
              sudo codesign --force --verbose --sign "$(InstallDistCerts.signingIdentity)" "$component"
          done

          # Sign the main app
          sudo codesign --force --verbose --sign "$(InstallDistCerts.signingIdentity)" \
            --entitlements "$(rootFolder)/safari/SafariDesktopExtension/SafariDesktopExtension/SafariDesktopExtension.entitlements" \
            "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.xcarchive/Products/Applications/SafariDesktopExtension.app"
        displayName: "Codesign"

      - task: Bash@3
        displayName: "Package Application"
        inputs:
          targetType: "inline"
          script: |
            productbuild --sign "$(InstallInstallerCert.signingIdentity)" --component "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.xcarchive/Products/Applications/SafariDesktopExtension.app" /Applications "$(Build.ArtifactStagingDirectory)/SafariDesktopExtension.pkg"

      - task: PublishBuildArtifacts@1
        inputs:
          PathToPublish: "$(Build.ArtifactStagingDirectory)"
          ArtifactName: "SafariDesktopExtension"
        displayName: "Publish Desktop Extension Artifact"
"Invalid Provisioning Profile" Error on TestFlight
 
 
Q