KATIE SKINNER: Hi, everyone. My name's Katie Skinner, and along with Jason Novak, we are going to be talking about privacy in your app this afternoon.
We are both members of Product Security and Privacy at Apple.
That means we work with teams all across Apple to build privacy into our apps and services. A few of the teams that I work closely with are Apple Pay, Siri, Proactive Assistant, Health, and our newest OS, watchOS.
First I am going to talk a little bit about why privacy matters at Apple and how we think about it. At Apple, we see privacy as a human right.
That's a guiding principle that we take every day into how we design our apps, our services, and new versions of iOS, OS X, and watchOS.
Users want their privacy respected when they use our products, and all developers, everyone in this room, shares that responsibility.
So when you are building your apps, be mindful of user privacy, and build privacy into your apps. Not only at Apple are we focused on building great products, we also are focused on building great tools for you, the developer community, to make it easy for you to respect user privacy and build privacy into your apps and services.
At the end of the day, all of our success relies on our relationship with our users.
And trust is key to maintaining that relationship.
We've all read stories in the press about breaches, about misuse of user data, and nobody in this room wants to be the next one in the news. Our platform is a place where users have excited about new experiences, excited about downloading new applications.
And it's all about keeping our app ecosystem healthy and thriving. And the trustworthiness of all of you is part of that.
So be trustworthy with our users. Now, users trust us with lots of sensitive data.
And we need to be good stewards of their data.
And architecting for privacy is the place to start to do that. Now, all data should have a retention policy.
Now, how do you come up with that retention policy? The place to start is how you will use that data.
Now, if you are no longer using that data, it's no longer serving a user need, then you should delete that data. All data that you are storing and the more data that you store makes you a richer target for attackers, a more valuable target.
So only collect the data that you need. I believe that all data collected carries risk, so you need to balance the value that you provide to users with the risks inherent in collecting and storing data. Now, you can mitigate this risk by applying data minimization techniques.
To learn more about the list of techniques and to see examples on how to apply them, go and watch User Privacy in iOS and OS X from last year's WWDC.
Aggregation, de-resolution, these are all ways to reduce the risk for the data that you retain.
But which techniques should you apply? The place to start is what is the use of the data? How are you going to use it? What questions are you going to answer? What decisions is this data driving? And if you can't come up with an answer to this question, you can't think of anything, then you shouldn't be retaining this data at all.
Apply the last technique on the list, minimization, and don't collect or transfer the data at all.
Now, for the data that you decide is actionable, all data sent off device should be protected in transit.
Later Jason will talk about App Transport Security, which is a new way in iOS 9 to make it easier to communicate securely with your services.
To reduce the risk, avoid transferring data off device when possible, especially think twice about sensitive data categories. This includes things like health data.
For example, during a cycling workout, there's information like the user's heart rate, the distance traveled, maybe the user's height and weight, calibration data, and all of that is processed on the paired devices to show what calories were burned during that workout.
None of that data is sent to server for processing. Now, data needs to be protected not only in transit but also when persisted.
First think about does the data need to be stored at all? Can it be transient? Can it be stored only in memory? Or does it need to be written to disk? On iOS and watchOS, take advantage of data protection, which I will be talking about more later.
If you are storing your data server-side, make sure you encrypt your data at rest.
With CloudKit, we make it simple to do this. Think about what identifiers are sent and stored with your data. Jason's going to talk in depth later about how to choose an appropriate identifier.
Now, you want to be clear with your users about what you are doing with your data, their data, how you are using it, if you are sharing it with third parties, and this is all part of transparency. Making sure users understand what's happening, avoiding any user surprise.
Now, one way to do this is to be clear to users about what data is being collected or stored. Give users a way to inspect their data.
Also, when you're collecting the data or when you give users a choice, it's at that point that you really want to give them the information to make a good choice. You can do that with things like purpose strings. When users are deciding if they want to grant you access to, maybe, their photos.
Also, you want to give users control.
Give them a way to remake their decision. If they decide later that they want a different decision for themselves.
Also, give them a chance to reset information you store or even delete. Now I am going to talk about some updates to our platforms to improve user privacy. I am going to talk about changes in iOS, OS X, and some of the foundational bits for watchOS.
So first on iOS, we are going to go back to last year.
Last year, we began using privately assigned MAC addresses for certain types of Wi-Fi scans.
In iOS 9, we've increased the number of scans that use privately assigned MAC addresses.
Note if your functionality is based on working with an external piece of hardware, make sure to test on iOS 9 because you cannot rely on the MAC address before authentication. Now, simply put, we think what apps are installed on a user's device are their business.
Users use their devices for lots of things, and they have lots of reasons for what kinds of apps they want to install, from health to financial to home.
Now, what apps a user has installed and what can be gleaned from them can be very sensitive. Trying to detect what apps a user has installed, either to identify them or to glean information, is contrary to the iOS security model.
Ultimately, the iOS security model the apps are isolated.
They live within their own sandbox, protecting them from other apps and processes. Trying to determine what apps a user has installed in their device is a subversion of the iOS security model.
Now, along those lines, the behavior of canOpenURL is changing this year.
The purpose of canOpenURL is to determine if an app can open a given URL resource.
This can be used to support functionality, like revealing new things that a user can do if an app is installed in the device.
One of the things you should be moving towards are extensions and universal links. They both support a lot of the same functionality, and we encourage you to move to that. But if you continue to use URL schemes when you build your app for iOS 9 and you want to call URL schemes, you will now need to declare them in your apps Info.plist. There is new key, LSApplicationQueriesSchemes, and here you will need to add the list of schemes you want to are canOpenURL on. Now you don't need to change handle calling canOpenURL. The actual API is not changing. But when you call canOpenURL, it will check your app's Info.plist and see if the scheme you are calling is declared.
So let's say you declared it. When you call canOpenURL on that scheme, it will return true if there is an app installed that does support the scheme.
Now, if there is not an app installed, it will return no.
So what if you didn't declare the URL scheme. No matter if there is an app or there is not an app that supports it, you will always be returned no. So for apps that are linked before iOS 9 and are running on iOS 9, they will be given 50 distinct URL schemes.
When you call the subsequent 51st scheme, you will be returned the value no.
These 50 URL schemes are not restarted when the user restarts the device. One alternate that I mention that is new this year is universal links. The great thing about universal links is if the user has the app installed, the link will open there.
But then there's also a fallback. If the app is not installed, it will open in the webpage of that app.
There's also changes coming to sysctl this year. Sysctl is a low-level API used for querying and setting system information.
It's designed to allow processes with appropriate privileges to view information, but as I said before, apps on iOS are not privileged to see other apps' information.
So there is a change to the iOS sandbox this year, and now there will no longer be able to call kern.proc, kern.procargs, kern.procargs2 and see data from any other processes then one's self.
This year, on both iOS and OS X, we will have a new extension point for content filtering.
Your block list -- the block list will apply to both Safari and any apps that use SafariViewController.
You should go and test with popular extensions to understand the impact this will have on your application or your webpage.
You should always be prepared for part of your content to fail to load and handle it appropriately.
They are local to a single process, and they are not shared. Note: If you have shipped your application in the App Store, there's no change for you.
You are already in this state.
If you use Web Clips or Dashboard widgets, please test on OS X El Capitan.
Now I am going to talk a little bit about our newest platform.
Over many years, we've seen iOS and OS X evolve and grow.
It's that experience that drove us to focus on making sure from the start that we laid the appropriate groundwork for privacy and security on this newest platform. We leveraged existing technologies, like data protection, our just-in-time alerts, and we think that these devices work closely together.
The user has a single relationship with the two devices, and so that's why lots of the settings are shared across.
This also includes your privacy settings for native WatchKit apps. So whether the user is interacting with your app on iOS, as a Glance, as a third-party complication, the same privacy settings apply.
We believe that the user has a single trust relationship with you as an app developer.
They don't think differently about, oh, can they access my photos on the Glance. They have one trust relationship. They trust you to access that data and protect that data or they don't.
So we think that this is important to focus on making sure that you embed and think about privacy from the beginning because your Glance may become the place where users interact with your app the most often. Also, in watchOS 2, Keychain is now on Watch. Now I am going to hand it over to Jason, who is going to talk more about how to choose an identifier.
JASON NOVAK: Thanks, Katie. Now I am going to talk a little bit about identifiers on iOS and watchOS. This is a topic that we've covered before in previous presentations, and you should review last year's WWDC talk to get a more in-depth look into. But I thought it was important to go over some of the lessons we learned from iOS before discussing how we brought identifiers to watchOS.
So identifiers are powerful. They are powerful because in and of themselves, they can reveal something about a user if you use something like a user's name, phone number, or email address to identify a user.
You can build a more privacy-friendly identifier by using things like randomly generated numbers or a UUID if you need a structured random number.
While a random number or UUID doesn't identify a person, depending what you log against it, how frequently you rotate identifiers, and what controls a user has, over time the identifier can be de-anonymized as you can log a lot of different kinds of data that may be identifying to a person, like app activities, search queries, messages, or location, depending upon what your app is doing.
And what this means is that all identifiers carry risk. Even though an identifier itself may be anonymous, if the data you hold against it isn't, then if there is a data breach, you still have to deal with a harm to customers' privacy, and the ensuing reputational damage as you'll lose customer trust. When I say data breach, that may cause you to think about hackers or other nefarious forces, but it may be as simple as an unencrypted laptop stolen out of the back of a car or backup tapes falling off the back of a truck.
As a result of the power identifiers, Apple spent a lot of time thinking about how identifiers operate and some best practices.
So first, before you use an identifier, ask yourself: Do you need one? Can you structure your data collection in some way that you have a database or dictionary of values that you are storing server side that the client sends up a value to your server and then you just increment a counter server side? If you determine that you really do need an identifier, think about what you are identifying and for how long you need to identify it for. Are you identifying a session and just trying to correlate activities across a single launch of your app? Are you trying -- and can you rotate the identifier every time the app opens or closes? Are you looking at temporal activity and you need to rotate the identifier every 5, 10, 15 minutes? We know that rotating identifiers has a lot of privacy-preserving power as it prevents the correlation of data over time, and we will walk through an example of that later. If you are identifying a user, how are you making it clear to the user that you are identifying them as opposed to an installation on device? Are you having them create an account with your service? Are you having them log in? Are you using words in the UI that make it very clear to them that this is about their experience? And after you thought about how you are explaining this to users, have you really thought about the risk you are taking on in collecting data that is associated with an individual's identity? Finally, if you are trying to collect data about an installation of your app on a device divorced from these other notions of users or sessions, have you designed your metrics to support the cases that we know occur with a user and their device, such as uninstalling an app or installing an app on a secondary device or backing up and restoring across devices and how the privacy preservation of a user that occurs there in terms of the identifiers being reset or persisting affect your metrics? Finally, you should consider how you scope your identifiers. It's easy to construct a world where a persistent identifier is used to track all of the user's activities across properties, but then a user's privacy is minimized. Lots of data is collected against a single identity that may never change that has different contexts, different meanings in different contexts. Moreover, users may not want to be tracked across all properties under a single identity. Contemplate scoping your identifiers so that you have different identifiers for different purposes with different data associated with them with different retention periods.
Now I am going to walk through an example of a specific architecture of identifiers that increases your privacy and decrease the risk you might face. It's easy to design a search service that logs all data to a user identifier, but then if this data is breached, then even if the identifier is anonymous, it allows for the ready re-identification of a user, as among other things, users search for themselves, and this scenario may result in a significant loss of user trust. For example, in this case, the identifier is anonymous. It's 123. But we can see a fairly clear set of facts. User 123 is thinking about getting engaged -- probably -- probably this past Saturday. They are probably not from San Francisco as they are looking for a flight from San Francisco. They are probably going to WWDC. And they may be John Appleseed, they may be interested in John Appleseed. We don't know. But given more data, we could probably figure out if this was a vanity search or not. On the other hand, if your search service uses rotating identifiers, then even if data is released, the exposure for a given user is minimized as the identifier rotates over time. In this case, if the identifier rotated every 15 minutes, we can't necessarily say that user 123 is the same as 456, is the same as 789.
So now I am going to talk about persistent identifiers for a moment, and because of the risk that they present to user privacy in terms of the ability to permit long-term tracking of users, they are not available on iOS and watchOS by design. Apple tries to surprise and delight its customers, and customers aren't delighted when they are being tracked without their knowledge. It's not in line with users' expectations that they are being tracked by an app under the same identity, even after they have uninstalled the app and reinstalled it or if they've done something more destructive like erase their device.
And finally, because persistent identifiers are persistent, users don't have control over them, and as Katie was saying earlier, we think of control as a very important part for user privacy. To try and balance the needs of developers to identify data and with the privacy of users, we've developed a set of purpose scoped identifiers on iOS so that developers can collect the data they need and use it in the analytics and advertising context while at the same time users have control to reset the identifiers and break the relationship between their current activities and whatever data has been historically collected about them. At the app level, we enable this by resetting the vendor identifier or the IDFV after a user has uninstalled all apps from a given team ID. And on the advertising context, we give users the ability to reset their advertising identifier by going to Settings, Privacy, Advertising, and tapping the Reset Advertisement Identifier. As a result a user can reset the identifier on their device without erasing all data on it and they break the link with whatever data has been historically collected. With watchOS 1, the vendor ID and the advertising ID were actually on the iPhone as the WatchKit extension itself ran on the iPhone. With watchOS 2, you will need to sync the vendor ID and advertising ID from the iPhone to the Watch and use it there. And you will need to maintain the vendor ID and advertising ID up-to-date. So now I am going to go over some best practices.
Determine if you need an identifier at all. Can you just send up a value and increment a server-side counter? Collecting data against an identifier brings responsibility as it brings risk. And if you can collect just a value in increment encounter, you have significantly increased user privacy and derisked your data collection.
Use a properly purposed scope identifier. Determine if you need to identify a session, a user, or a device and use an identifier of the proper scope for your app's purpose.
iOS and watchOS offer identifiers for you, so use them instead of building your own. Trying to build a persistent identifier that survives device reset and other destructive actions like removing your app is bad for user privacy and bad for your app. If you are using private APIs to build a persistent identifier, you are in violation of the App Store terms, and there will be consequences.
Finally, follow the guidelines for the identifiers that are provided, and one of the most important guidelines you can follow is to check the value of Limit Ad Tracking before you call the advertisingIdentifier and to always get the current value of the advertisingIdentifier.
A user can reset the value of the advertisingIdentifier at any time, in addition to enabling ad tracking. Which also causes a reset of the advertisingIdentifier. Because of this, you should always be sure that you have the current value, and you should never cache it. Finally, we are going to talk a little bit about reporting. We know that many of you have reporting obligations to your partners, but we think it's important to maintain user privacy when reporting to third parties. We thought a lot about how to report on users, and you can see a lot of our learnings embedded in App Analytics. And there are sort of three big ideas here that you can implement when reporting. Report insights about your users. Report aggregates. And set a threshold.
What do I mean by report insights? Instead of if a partner wants to know who uses your app frequently and say give us all data about your app's usage so that they can calculate that, instead, agree upon a definition of common usage, run that calculation, and on your data, and provide the results of that calculation instead of giving over the raw data.
The next step to protecting user privacy would be to aggregate. Instead of saying which users are frequent users, say how many frequent users you have, what percentage of your user base are frequent users. And finally, require thresholds in reporting. If you are going to report that you have one frequent user and you have one user of your app and you are going to provide some information about them from an audience standpoint, like zip code, you have effectively de-anonymized your user. Before you provide personal information be sure to have a threshold, so that you're not de-anonymizing a person, and they're in a group. I am now going to explain some best practices on how to prompt for user data and then extend those to the Watch Just a refresher, on iOS and OS X, when you want to access data classes, the operating system doesn't give access to that data until the user makes a decision as to whether or not to give your app access to that data.
So that it's clear to users why an app needs this data and so that you can be transparent with users about your collection and use, we provide you with a place in the prompt where you can provide an explanation. This is called a purpose string. You can set them for the various protected data classes in your apps and Info.plist, and we think that if users understand why you are asking for their data, they are more likely to make the choice that's right for them.
As Katie said earlier, given the limited real estate available on the watch and our perspective on transparency and consent to control, a lot of thought went into how apps on the watch could access user data.
First, just like on iOS and OS X, apps on watchOS can't access a user's data until the user has approved that.
Unlike on iOS or OS X, on watchOS, a user can't accept or deny a just-in-time prompt on the device itself. Rather, they are directed to their iPhone. As Katie was saying, we think of the iPhone and the paired Watch as a tightly coupled experience, and the privacy decisions that users make on one platform affects them on the other. Given the limited real estate on the watch, we thought that it made more sense to present the choice on the iPhone, where the user will see the prompt on the larger screen, including the purpose string, explaining why your iPhone app and Watch app want access to that data.
Unlike in iOS where you get a yes or no answer, you can prompt, get dismissed, or otherwise not have the user make a choice when you prompt from the watch, and as a result be left in an unset state. In this unset state, you will be able to prompt again later. Just to give a concrete example of that unset state, a user could go on a run with their Watch but not their Phone, launch your app on the Watch. Your app could prompt. The prompt would be dismissed. And your app would have to continue to run without access to that data.
But at a later point in time, your app could prompt again. Now, as Katie said earlier, the settings, including your privacy settings, are shared between the Watch and the iPhone.
And we think that users have a single relationship with your app, a single relationship with the iPhone and the Watch, so as a result, we've combined these single relationships into a single relationship of settings for the iPhone, the watch, and your app. And this is something that exists elsewhere in our platforms. On iOS, if a user makes a privacy decision for your app, then all facets of your app have access to that data. If you prompt for a location in your app, your extensions can use it, and if the first time that a user encounters a prompt for your app is in the extension, your app will also have access to that data. On the Watch, the decisions that a user makes carries over to all of your Watch app, the app itself, your Glance, and your Complication.
When a user gives permission for one aspect of your app, they give permission for all aspects of your app. Now that you know what data is available on iOS, OS X, watchOS, and how to prompt for them, we think it's also important to consider how to protect user data once a user has given you access to it with a new set of OS releases. We have new security features you should leverage and be aware of. The first of these is App Transport Security. To secure user communications by default, we introduced App Transport Security to iOS 9 and OS X El Capitan. By default, your communication through higher level APIs will need to be encrypted using TLS version 1.2 with forward secrecy. If you try to make connection that doesn't follow this requirement, an error will be thrown.
If your app does need to make a request to an insecure domain, you have to specify this domain in your app's Info.plist. This will be gone into more detail in the Networking with NSURLSession tomorrow at 9 a.m. in Pacific Heights as well as in the security talk later this afternoon.
If you do want to declare an exception to App Transport Security, you need to declare the exception in your app's Info.plist and then optionally set one or more of these keys.
Now I am going to talk about rewards cards.
With iOS 9, rewards cards can now be presented with Contact list transactions. We know that some rewards cards use a person's phone number, email address, or other personally identifiable data as the identifier for the rewards cards. So to protect user privacy in the presentation of rewards cards and Contact list transactions, we provided developers with an easy way to encrypt this data when it goes over the Contact list transaction channel.
All you have to do is modify your pass.json with this new nfc dictionary where you specify the message, the identifier, and your public encryption key. From there, iOS takes care of the encryption of the message for you when the rewards card is presented in the contactless payment. With the App Search, App history, and App links in iOS 9, it now means you can now store data about your app outside of your app. As a result, you have to be a good steward and protect the data for your users both when it is inside your app and when it is stored outside of your app.
There's a great talk about this on Wednesday at 11 a.m. Please go check this out as they will go into much greater depth than I can, but I am going to talk briefly about two ways an app can have data indexed and the privacy impacts of them.
The first is NSUserActivity, which is an API introduced in iOS 8 to support Handoff. In iOS 9, we extended it so you can use NSUserActivity to create views of your app this can be indexed and then searched for by user to return to. For example, in your Recipe app, when a user looks at a poutine recipe, you can create a NSUserActivity for that view and have it indexed. Then when the user searches for poutine on their phone later, one of the results will be a link to the recipe they were looking at before. Think of it as handing off to yourself in the future instead of on to another machine. We thought about how to make search privacy friendly from the ground up, and part of how we did so was to have the default be not to index data.
That's right. By default, NSUserActivity continues to be for Handoff. If you want to make a view that's searchable, you have to set the eligibleForSearch property to true, and if you want to make that view publicly indexable -- and we will get into that later -- you have to make that eligibleForPublicIndexing property set to true as well.
The other property that you should set when you are making data indexable is the expirationDate, since as Katie discussed earlier, part of protecting user privacy is protecting their data by deleting it when it's no longer relevant to the user.
So now I am going to talk a little bit about NSUserActivity and public indexing.
NSUserActivity are a great light-weight way to make your apps searchable. We made indexing privacy friendly by not indexing it by default and leaving it to developers to determine whether or not to index a specific view.
But we understand that some developers have apps that contain public content that they want to be searchable on all devices.
To enable this, we came up with a way to protect user privacy while also indexing additional data.
When you make a view eligible for search and then mark it eligible for public indexing if it contains only publicly available data, then when a user searches for that view and engages with it, a hash of that view is sent to Apple.
After multiple devices, hash this view and send the hash to Apple.
Eventually, when the threshold is exceeded, the actual view will be sent to Apple, and this is so that views accidentally marked public aren't unintentionally sent up. That's NSUserActivity. I am going to talk a little bit about Core Spotlight now. Core Spotlight now is a new API in iOS 9 that you can use to make user content in your app searchable, things like Mail, Contacts, Calendars. This is derivative data, and you need to protect it the same way you protect underlying data yourself in your app. The first up here is a set data protection class on it just as you do data in your app. The next is to practice data management with the derivative data in the index. You can store -- first you should store relevant user data -- for instance, does anyone need to see drafts or deleted documents? When a user updates documents in your app, you should update the copy of those documents in the index.
When a user deletes a document in your app, you should delete the document in your index. Because users have multiple ways of deleting documents in apps, like deleting all files of a type or of a folder we have made it easy to delete multiple items at once or to delete all items from search.
That's a brief overview of some of the new privacy protecting features in iOS 9. I am now going to hand it over to Katie to talk about some of the existing technologies you should be adopting if you haven't already.
KATIE SKINNER: Thanks, Jason. I want to highlight a few of the existing technologies that we have that makes it easy to protect user data without having to do work like writing crypto primitives yourself. Touch ID is a great way to protect your app or protect data within your app.
You can use Apple Pay in app to make it so you don't have to go through the process of creating and accepting user data and credit card data. Now I am going to dive a little bit deeper on privacy policies and data protection.
In addition to protecting your user's data technically, it's important to explain to users how you are going to use their data and if you are going to share it with a third party. We actually require privacy policies for certain types of applications, including apps that link to HealthKit.
This is incredibly powerful encryption, and you can easily leverage it without having to write any crypto code yourself.
Now, every iOS, data protection is implemented by managing a hierarchy of keys.
It builds on the hardware encryption that's built into every iOS and watchOS device.
Data protection is controlled on a per-file basis, so each file is assigned to a class.
Accessibility is determined whether the class keys have been unlocked. So there are four data classes, and I am going to go through each one. But the one that you may be most aware of is NSFileProtectionComplete UntilFirstAuthentication. As of iOS 7, all third-party app data by default is this data class.
Now, your apps can't run until after boot, until after the user puts in their passcode. So all of your data should at least be this protection.
We know that some developers are using no protection, but there's no reason, no value for doing that.
So I'm going to quickly go through the different data classes in the behavior. As you can see, with no protection, even if the user enters the passcode or not, the data is always unlocked. It's always accessible.
Lastly -- so next, protected until first authentication, this is your default class.
Now, it's not accessible on boot, but as soon as a user enters their passcode, the data is accessible, and then it's still accessible when the device is locked. Next is protected until open. This is designed for data that comes in and is sensitive while the device is locked. So there's two types of access, reading and writing. So the device boots, and there's no access. The user enters their passcode. Now you can both read and write.
The device locks again. You are unable to read, but you can still write data.
Lastly, complete protection. Now, this is for most sensitive kinds of data, including health data, financial information.
When the device boots, the data is unaccessible.
When the user enters their passcode, the data is available. The device locks, the data is no longer available.
This is a great chart to look at later to think about which data protection class you should be using.
And lastly, make sure you test with data protection enabled. You can check this by going to Settings, Touch ID & Passcode, scrolling down to the bottom, and see if data protection is enabled. Now, we've talked about a lot of things, and you need to make sure that you take your apps and test on iOS and OS X. You want to understand the impact to these changes and make sure you are still providing a great experience for your users. Prompt with purpose.
Make sure to minimize data and keep it up to date.
Leverage some of the platform technologies that we talked about today.
And lastly, user privacy is our shared responsibility.
We have to do this together, so both us and you. It's our responsibility to protect the privacy rights of our users.
Thank you very much.
[ Applause ]
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.