Adding Apple Privacy Manifest Support to .NET iOS & .NET MAUI apps

Gerald Versluis

Apple is introducing a privacy policy for including privacy manifest files in new and updated applications targeted for iOS, iPadOS, and tvOS platforms on the App Store. Note that macOS apps are excluded at least for the time being.

The privacy manifest file (PrivacyInfo.xcprivacy) lists the types of data your .NET MAUI applications, or any third-party SDKs and packages collect, and the reasons for using certain Required Reason APIs categories.

At the time of writing Apple is already sending out notices about including this policy in your apps. As of May 1, 2024, this will be mandatory in order to pass the App Store review. In this post we will see what is needed for your .NET MAUI, .NET for iOS and Xamarin apps in order to stay compliant and be able to continue releasing updates for your apps.

What is the Apple Privacy Manifest?

A couple of years ago Apple started gathering information from you about the data you collect in your iOS apps and how you use that data. This information is then shown to the end-user in the App Store listing of your app. An example of this can be seen below.

The App Store listings for the Microsoft Word and Azure app on macOS and iOS respectively, showing the App Privacy section.

While this is a great step in the direction of transparency to your user and protecting their privacy, it might not always be clear to you, the app developer, what data you are actually collecting. You know what the data is that you are gathering in your app and how you process it, but it is likely that you are using third-party libraries and those might do their own processing. For instance, by building your app with .NET MAUI, you’re already using a framework that might use certain APIs which require an entry in the privacy report.

To enrich the privacy report data even more, Apple is taking this a step further with the introduction of the Apple privacy manifest. This manifest, which is another XML-based metadata file, should be included in your app, but also library developers should now include one in their library where needed.

This way, Apple can cascade all the different PrivacyInfo.xcprivacy files from frameworks, libraries and your app into one, very complete privacy report that is then shown on the App Store listing for your app.

Privacy manifest and .NET

What does that mean for your .NET based iOS apps? A privacy manifest needs to be included in your .NET MAUI and .NET for iOS app as well. Luckily, there is no need for extra support here, just like with the .NET for iOS and .NET MAUI apps. You can do everything that is required with the tools and SDKs that you have today.

The PrivacyInfo.xcprivacy file is a metadata file in XML format, much like the Info.plist that you probably already know. This file should be filled with the privacy entries that are applicable to your application. A list of the APIs that currently need an entry in the privacy manifest can be found on the .NET for iOS repository along with detailed instructions on when to add which entry in the manifest and how.

Minimum privacy manifest for .NET applications

Depending on what SDKs you use, there are three layers that could potentially use any of the Required Reasons APIs:

  • .NET runtime and Base Class libraries (BCL)
  • .NET for iOS SDK
  • .NET MAUI SDK

As part of the SDKs mentioned above, we have identified three categories used in these SDKs that require an entry in the privacy manifest:

Therefore, all .NET applications must include the above categories in the privacy manifest file. Below are the contents of the PrivacyInfo.xcprivacy file when you are building an iOS app based on .NET.

To clarify, all applications built with .NET that run on iOS, will need the below manifest at the very minimum. On top of that you should identify APIs that you are using in your own code as well as entries coming from third-party libraries and frameworks.

Note: The following contents are verified only for .NET MAUI versions 8.0.0 and later.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NSPrivacyAccessedAPITypes</key>
    <array>
        <dict>
            <key>NSPrivacyAccessedAPIType</key>
            <string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
            <key>NSPrivacyAccessedAPITypeReasons</key>
            <array>
                <string>C617.1</string>
            </array>
        </dict>
        <dict>
            <key>NSPrivacyAccessedAPIType</key>
            <string>NSPrivacyAccessedAPICategorySystemBootTime</string>
            <key>NSPrivacyAccessedAPITypeReasons</key>
            <array>
                <string>35F9.1</string>
            </array>
        </dict>
        <dict>
            <key>NSPrivacyAccessedAPIType</key>
            <string>NSPrivacyAccessedAPICategoryDiskSpace</string>
            <key>NSPrivacyAccessedAPITypeReasons</key>
            <array>
                <string>E174.1</string>
            </array>
        </dict>
        <!--
            The entry below is only needed when you're using the Preferences API in your app.
        <dict>
            <key>NSPrivacyAccessedAPIType</key>
            <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
            <key>NSPrivacyAccessedAPITypeReasons</key>
            <array>
                <string>CA92.1</string>
            </array>
        </dict> -->
    </array>
</dict>
</plist>

For .NET MAUI specifically you might need to uncomment that last entry. Only if you use the Preferences APIs, you will also need the entry for CA92.1. The reason why you don’t need it otherwise is because the compiler will trim all unused APIs, including the ones used by Preferences, unless you reference them in your code.

To add this file to your .NET for iOS project, copy the above contents and paste them in a file named PrivacyInfo.xcprivacy and place that under the Resources folder. This is all that is needed to package the file into the iOS app at the root of the bundle.

For .NET MAUI apps, copy the above contents and paste them in a file named PrivacyInfo.xcprivacy and place that under the Platforms/iOS folder. Then edit your .NET MAUI project csproj file with your favorite text editor and add the below section somewhere under the <Project> node.

<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
    <BundleResource Include="Platforms\iOS\PrivacyInfo.xcprivacy" LogicalName="PrivacyInfo.xcprivacy" />
</ItemGroup>

This will make sure that the manifest file is in the root of your bundle.

More information about the privacy manifest and which entries might be needed for your app can be found on the Microsoft Learn documentation.

Privacy manifest for Xamarin.iOS and Xamarin.Forms

All of the above also applies to Xamarin.iOS and Xamarin.Forms apps. Just like the .NET for iOS and .NET MAUI apps, luckily no additional support is needed here, everything that is needed can be done with the tooling and SDKs available to you today.

You can create a PrivacyInfo.xcprivacy file and include that in your project which should satisfy the App Store requirements. Make sure to create a complete privacy manifest file that has all the entries needed to describe your app and add that to your project.

Make sure that for both the Xamarin.iOS project and the Xamarin.Forms project the file is marked as bundle resource (set the Build Action to BundleResource), which should add it correctly to the resulting binary. For Xamarin.Forms, adding the manifest file is only needed in your iOS project.

More instructions on which entries might be needed for your app and how to add the PrivacyInfo.xcprivacy file to your Xamarin projects, can be found on the .NET for iOS repository. There is also Microsoft Learn documentation available for .NET MAUI, which still applies also to Xamarin in terms of what the privacy manifest should look like.

Mac Catalyst and macOS apps

At this time it seems that macOS apps, including Mac Catalyst do not seem to need privacy manifest entries for the required reasons APIs. However, a manifest file and relevant entries are still needed if your app, or any SDK you are using inside of your app, is collecting personal data. Please refer to the Apple documentation for more information about the required entries.

Adding the PrivacyInfo.xcprivacy file to your project follows the same procedure as described above, however you should place the file under the Contents/Resources/ subfolder in your macOS app bundle instead of in the root as for iOS.

Third-party libraries

Please note that ultimately, it is your responsibility as the app developer that you provide the correct privacy manifest for your apps, regardless of any libraries or frameworks you are using. If you keep getting warnings from the App Store review system, ensure that you have added all necessary entries that cover your app code.

When you are certain that the warning is not triggered by code in your app, make sure to check with third-party libraries and frameworks that you might be using that they included a manifest file as well where needed.

For open-source projects, you can easily inspect the code to see if any APIs are used that require an entry in the manifest. Please refer to Microsoft Learn for a list of the APIs that require an entry in the privacy manifest.

If the project author is not able to provide a manifest file for their product, you can solve this by adding the identified required entries in your own PrivacyInfo.xcprivacy file. Make sure that you understand what the APIs are used for and what they do so you can confidently convey this information to your users when needed.

Are you a library author?

Maybe you are a library maintainer yourself, in that case everything described in this blog post and the linked documentation is also applicable to your project.

At the time of writing we are still investigating how we can best facilitate you (and therefore your users) with these new requirements by Apple. For the time being our recommendation is to inspect your codebase, identify code that requires entries in the privacy manifest and make that information available to your users so they can add it to their apps manifest. You will probably want to include some explanation of why those entries are needed.

If you maintain a binding library, you will want to look into updating the native library. Chances are that a privacy manifest file is already included in there. However, binding that new version of the library will not automatically include the required manifest file in the end users app. Please, for the time being, still pass on this information to the users so they can include it manually.

Verify adding the manifest

In order to verify if the privacy manifest has been added correctly, submit your app including the manifest to the App Store for review. The Apple systems will do a number of automated checks on the provided binary. When something is not correct, they will send you an email at the email address that is registered for your Apple Developer account.

If you do not receive any emails, or the email does not say anything specifically about the privacy manifest, you can safely assume it was added correctly.

Summary

Please refer to our extensive description of the Apple privacy manifest and make sure that you understand what is needed for your app. Ultimately, it is your responsibility to inform your users about how you process their data and provide that information the correct way to Apple.

To ensure that your app releases are not disrupted, start adding this to your apps today. By doing so well before the May 1, 2024 deadline you will make sure that you can continue to release your apps after that.

Remember that you as the developer are always responsible for making sure the privacy manifest is correct, up-to-date and included in your apps. At the time of writing (March 2024) we have identified all the APIs that require an entry in the manifest, but over time these may change. Always be sure to check the Apple documentation for the latest requirements.

If you have any questions, please refer to this issue on the .NET for iOS repository to find experiences from other developers and answers to questions from our engineering team.

20 comments

Leave a comment

  • John Gathairu 1

    Thanks Gerald, article came right on time!

    • Gerald VersluisMicrosoft employee 0

      Perfect, glad to hear that! Please let us know your experience with all this. It’s a bit of a hassle to set it up initially, and we’ve been looking into it quite extensively so happy to answer any questions or address concerns.

  • Thibault Durand 0

    Very good article and great job from the .NET teams to research and document this!

    A few precisions:
    #1 I think the three you listed are mandatory for .NET-ios apps, but MAUI apps (may*) require the NSUserDefaults one (since shared preferences use NSUserDefaults)

    (*See Geralds clarification)

    2 https://developer.apple.com/news/?id=3d8a9yyh

    > Starting March 13: If you upload a new or updated app to App Store Connect that uses an API requiring approved reasons, we’ll send you an email letting you know if you’re missing reasons in your app’s privacy manifest. This is in addition to the existing notification in App Store Connect.
    > Starting May 1: You’ll need to include approved reasons for the listed APIs used by your app’s code to upload a new or updated app to App Store Connect. […]

    That’s only seven weeks during Apple will have sent warnings to app updates sent to review. So a great many developers (that don’t send update so often) will only find out once submitting their apps to the Store.

    3 As of now:

    – The warnings are not part of the analysis in Transporter
    – Nor are they sent during the “Analyzing build” phase after you have sent your build using Transporter
    – The warnings are sent only when you hit “Submit for review”
    (So you may find out quite late in the process…)

    • Gerald VersluisMicrosoft employee 0

      Number 1 not entirely correct. Unless you are specifically using the Essentials Preferences APIs, the Apple APIs are trimmed, so they will not be in your app and thus that 4th entry is not needed. This is better described in the docs, and will be part of our templates: https://github.com/dotnet/maui/pull/21350/files

      For the rest, indeed Apple is not leaving a lot of room here for people to implement this. Luckily the technical part of the implementation is not that hard, hopefully people will have an easy enough time to gather all the right entries for their apps.

      The way I have been testing it is to submit an app for Test Flight, but only if you submit it to external testers it will trigger the privacy manifest check and potential warning email.

      This will probably, hopefully become better in the near future.

      • Thibault Durand 1

        Thank you for the clarification about trimmed APIs! I am using the Preferences API so that explains why I got the warning for NSUserDefaults then.

  • Zachoval Tomáš 1

    Thank you Gerald. Nice work, you should get bonuses for that!

  • Schmidt, Helmut 1

    Is there maybe any script/tool/etc. to scan a project and its dependencies for possible entries in the manifest?
    I find sentences like
    Please note that ultimately, it is your responsibility as the app developer that you provide the correct privacy manifest for your apps, regardless of any libraries or frameworks you are using.
    pretty optimistic, considering the average dozens of 3rd party Nugets in a MAUI project.

    What is one supposed to to for compliance?
    Comb through all dependencies with a decompiler?

    • Gerald VersluisMicrosoft employee 1

      If you really want to you can submit your app for review, see the details of the warning email you get back from Apple and add those entries to your manifest, that is probably the easiest way to do it.

      However, you probably want to understand what APIs are used and why so you’ll be able to explain that to your users. I imagine that is also the whole reason Apple is doing this, to create clarity and transparency around how sensitive data is being processed.

      That means a combined effort for the whole ecosystem, in our case the .NET one, but ultimately the whole Apple developer ecosystem.

  • Antoine Hébert 0

    Hey Gerald, great article thanks!

    There’s a typo in the PrivacyInfo.xcprivacy content. As described in the doc: https://learn.microsoft.com/en-ca/dotnet/maui/ios/privacy-manifest?view=net-maui-8.0#add-required-entries-to-the-privacy-manifest

    The NSPrivacyAccessedAPITypes key is missing in the example provided!

    It should be structured like so:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>NSPrivacyAccessedAPITypes</key>
        <array>
            <dict>
                <key>NSPrivacyAccessedAPIType</key>
                <string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
                <key>NSPrivacyAccessedAPITypeReasons</key>
                <array>
                    <string>C617.1</string>
                </array>
            </dict>
            <dict>
                <key>NSPrivacyAccessedAPIType</key>
                <string>NSPrivacyAccessedAPICategorySystemBootTime</string>
                <key>NSPrivacyAccessedAPITypeReasons</key>
                <array>
                    <string>35F9.1</string>
                </array>
            </dict>
            <dict>
                <key>NSPrivacyAccessedAPIType</key>
                <string>NSPrivacyAccessedAPICategoryDiskSpace</string>
                <key>NSPrivacyAccessedAPITypeReasons</key>
                <array>
                    <string>E174.1</string>
                </array>
            </dict>       
        </array>
    </dict>
    </plist>
    • Gerald VersluisMicrosoft employee 0

      You are absolutely right, no clue how I got that mixed up. I have updated the post so that it also provides some clarity around another entry that might be needed to .NET MAUI.

      Thanks for letting me know!

  • Geert Geerits 0

    Hi Gerald, thanks voor your article.
    I have done everything as stated in your article and still I receive this from Apple:

    Although submission for App Store review was successful, you may want to correct the following issues in your next submission for App Store review. Once you’ve corrected the issues, upload a new binary to App Store Connect.
    ITMS-91053: Missing API declaration – Your app’s code in the “RubiksCube” file references one or more APIs that require reasons, including the following API categories: NSPrivacyAccessedAPICategoryDiskSpace. While no action is required at this time, starting May 1, 2024, when you upload a new app or app update, you must include a NSPrivacyAccessedAPITypes array in your app’s privacy manifest to provide approved reasons for these APIs used by your app’s code. For more details about this policy, including a list of required reason APIs and approved reasons for usage, visit: https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api.

    ITMS-91053: Missing API declaration – Your app’s code in the “RubiksCube” file references one or more APIs that require reasons, including the following API categories: NSPrivacyAccessedAPICategoryFileTimestamp. While no action is required at this time, starting May 1, 2024, when you upload a new app or app update, you must include a NSPrivacyAccessedAPITypes array in your app’s privacy manifest to provide approved reasons for these APIs used by your app’s code. For more details about this policy, including a list of required reason APIs and approved reasons for usage, visit: https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api.

    ITMS-91053: Missing API declaration – Your app’s code in the “RubiksCube” file references one or more APIs that require reasons, including the following API categories: NSPrivacyAccessedAPICategorySystemBootTime. While no action is required at this time, starting May 1, 2024, when you upload a new app or app update, you must include a NSPrivacyAccessedAPITypes array in your app’s privacy manifest to provide approved reasons for these APIs used by your app’s code. For more details about this policy, including a list of required reason APIs and approved reasons for usage, visit: https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api.
    Apple Developer Relations

    • Gerald VersluisMicrosoft employee 0

      Can you maybe expand a little on what “everything as stated in your article” means exactly?

      Did you also add the BundleResource entry to your csproj file? Have you verified that the PrivacyInfo.xcprivacy file is actually in the root of your app bundle?

      Maybe it’s easier if you reach out directly. We have been testing this and it works, so there is probably a small thing still missing in your project.
      Please send an email to gerald.versluis@microsoft.com so we can figure it out!

      • Geert Geerits 1

        The status is now ‘Waiting for Review’ without any issues for the moment.
        Thank you very much.

  • 현명 지 0

    Hi,

    If I use the Essentials Preferences API in Xamarin/Maui, do I need to add NSPrivacyAccessedAPICategoryUserDefaults?

  • Kalixt 0

    Does someone figured out way to add privacy reasons and purposes if you are using telemetry and analytics ? Also there are a ton of people that use NFC, GPS and other staff so it would be great if it was documented.

    • Gerald VersluisMicrosoft employee 0

      All the relevant documentation (that is available today) is linked in the blog post.

      Using telemetry and analytics and what is needed for that depends on your provider and any libraries they provide for doing it, so you might want to get in touch with them. Otherwise, read through the documentation and determine what is applicable to you and what the relevant entries are that you need to add.

      • Kalixt 0

        Yes, I get that you need to know what type of data you collect and everyone will have it different but I was hoping for example of where to place all that staff correctly. We don’t have and we won’t have privacy report from ‘Microsoft.AppCenter.Analytics’ as it’s scheduled for retirement and people need some point to start off.

Feedback usabilla icon