Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Importance of Privacy on iOS

The Importance of Privacy on iOS

A lot of time Privacy of my data as a user is not a priority for Developers. Wether it’s my calendar, my contacts, my location, I want as a user to be able to use an app without all of those attacks in my privacy.

I want to summarise everything an iOS developer should do to ensure the most critical user can still use my app in some regards, and not just say “I need all your information” like on other platforms.

This is the beauty of iOS, being able to fine grained (although not enough) so let’s do this all together, as a beautiful community concerned by Privacy.

Manu Carrasco Molina

June 07, 2018
Tweet

More Decks by Manu Carrasco Molina

Other Decks in Technology

Transcript

  1. The Importance of Privacy on iOS • Manu @stuffmc Carrasco

    Molina • Apple Technologist @ .com • Founder of Swi"Conf.com [Est. 2012] • Dad of 4, Environment & Refugees Activist Notifications (Can't decide when) @stuffmc • The Importance of Privacy on iOS 1
  2. What we'll cover • Siri & Search • Photos •

    Contacts • Location • Calendar @stuffmc • The Importance of Privacy on iOS 4
  3. What we won't do • The other parts. Other flavor

    of this talk. • Be exhaustive. We'll scratch o"en. • The whole APIs. Only the privacy parts. • GDPR / DGSVO / RDPG. Good Stuff though. • Maybe I don't have all the new iOS 12 things ;) @stuffmc • The Importance of Privacy on iOS 5
  4. My Privacy.app • Super simple demo app • Link to

    Privacy settings • Contacts, Calendar, Location • ... and... Wait, Siri?! @stuffmc • The Importance of Privacy on iOS 6
  5. ! Siri & Search • By default for every app

    • Settings sometimes for app • Sometimes not. • Always in Siri & Search Based on how you use your app. SAY WHAT?! @stuffmc • The Importance of Privacy on iOS 7
  6. Ask Permission PHPhotoLibrary.requestAuthorization { switch $0 { case .authorized: case

    .denied: case .notDetermined: // User has not yet made a choice case .restricted: // Parental controls being in place? } } @stuffmc • The Importance of Privacy on iOS 10
  7. Ask Permission PHPhotoLibrary.requestAuthorization { switch $0 { case .authorized: case

    .denied: case .notDetermined: // User has not yet made a choice case .restricted: // Parental controls being in place? } } App has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an UsageDescription key with a string value explaining to the user how the app uses this data. @stuffmc • The Importance of Privacy on iOS 11
  8. Ask again @IBAction func givePermission() { if let url =

    URL(string:UIApplicationOpenSettingsURLString) { UIApplication.shared.open(url, options: [:], completionHandler: nil) } } @stuffmc • The Importance of Privacy on iOS 13
  9. A picture worth a 1000 Metadata class Image: NSObject, MKAnnotation

    { var asset: PHAsset var dateFormatter: DateFormatter init(asset: PHAsset, dateFormatter: DateFormatter) { self.asset = asset self.dateFormatter = dateFormatter super.init() } var coordinate: CLLocationCoordinate2D { get { return asset.location!.coordinate } } var title: String? { get { return dateFormatter.string(from: asset.creationDate!)} } } @stuffmc • The Importance of Privacy on iOS 16
  10. UIImagePickerController User decides5 which pictures he gives let picker =

    UIImagePickerController() picker.sourceType = .photoLibrary picker.delegate = self present(picker, animated: true) { } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { print(info) } 5 This is simple UIKit, btw, not in the Photos framework. @stuffmc • The Importance of Privacy on iOS 17
  11. Contacts NSContactsUsageDescription TCC__CRASHING_DUE_TO_PRIVACY_VIOLATION__: App has crashed because it attempted to

    access privacy-sensitive data without a usage description. Info.plist must contain an NSContactsUsageDescription key with a string value explaining to the user how the app uses this data. @stuffmc • The Importance of Privacy on iOS 20
  12. Out of Process Alert • Start App • Wait Alert

    • Quit app • Allow app @stuffmc • The Importance of Privacy on iOS 22
  13. Contact The good (developer) let predicate = CNContact.predicateForContacts(matchingName: "Appleseed") let

    descriptors = [CNContactGivenNameKey, CNContactFamilyNameKey] CNContactStore().unifiedContacts(matching: predicate, keysToFetch: descriptors) @stuffmc • The Importance of Privacy on iOS 23
  14. Contact — The bad let descriptors = [all the friggin

    properties] <CNContact: givenName=John, familyName=Appleseed, organizationName=(null), phoneNumbers=( "<CNLabeledValue: label=_$!<Mobile>!$_, value=<CNPhoneNumber: stringValue=888-555-5512, initialCountryCode=(null)>>", "<CNLabeledValue: label=_$!<Home>!$_, value=<CNPhoneNumber: stringValue=888-555-1212, initialCountryCode=(null)>>" ), emailAddresses=( "<CNLabeledValue: label=_$!<Work>!$_, [email protected]>" ), postalAddresses=( "<CNLabeledValue: label=_$!<Work>!$_, value=<CNPostalAddress: street=3494 Kuhl Avenue, city=Atlanta, postalCode=30303, country=USA, countryCode=us>>", "<CNLabeledValue: label=_$!<Home>!$_, value=<CNPostalAddress: street=1234 Laurel Street, city=Atlanta postalCode=30303, country=USA, countryCode=us>>" )> @stuffmc • The Importance of Privacy on iOS 24
  15. Contact — The ugly predicate = CNContact.predicateForContactsInContainer( withIdentifier: store.defaultContainerIdentifier() )

    Every Single Contacts of your users! Go ahead, upload to the server!!! @stuffmc • The Importance of Privacy on iOS 25
  16. Use iMessage, Wire4 or else • Doesn't ask acess to

    your address book • Doesn't Geo Locate you • On iOS Signal & Telegram asks as well • Haven't tried Threema myself yet 4 Because not everybody has Apple Hardware :( @stuffmc • The Importance of Privacy on iOS 27
  17. Always check authorisation status [Contacts] Access to Contacts denied with

    error: Error Domain=CNErrorDomain Code=100 "Access Denied" This application has not been granted permission to access Contacts. let status = CNContactStore.authorizationStatus (for: .contacts).rawValue @stuffmc • The Importance of Privacy on iOS 28
  18. Always check authorisation status CNAuthorizationStatus /*! The user has not

    yet made a choice regarding whether the application may access contact data. */ CNAuthorizationStatusNotDetermined = 0, /*! The application is not authorized to access contact data. * The user cannot change this application’s status, possibly due * to active restrictions such as parental controls being in place. */ CNAuthorizationStatusRestricted, /*! The user explicitly denied access to contact data for the application. */ CNAuthorizationStatusDenied, /*! The application is authorized to access contact data. */ CNAuthorizationStatusAuthorized } @stuffmc • The Importance of Privacy on iOS 29
  19. Always check authorisation status if [.authorized, .notDetermined].contains( CNContactStore.authorizationStatus(for: .contacts)) {

    // You can proceed and/or ask for the first time } else { // Won't have access til some user/admin action happens } @stuffmc • The Importance of Privacy on iOS 30
  20. CNContactStore — Me only for macOS? unifiedMeContactWithKeys(toFetch: [CNKeyDescriptor]) macOS 10.11+

    Not available on iOS Why, ?! ! @stuffmc • The Importance of Privacy on iOS 31
  21. Which Properties are accessed? CNContactNamePrefixKey CNContactGivenNameKey CNContactMiddleNameKey CNContactFamilyNameKey CNContactPreviousFamilyNameKey CNContactNameSuffixKey

    CNContactNicknameKey CNContactOrganizationNameKey CNContactDepartmentNameKey CNContactJobTitleKey CNContactPhoneticGivenNameKey CNContactPhoneticMiddleNameKey CNContactPhoneticFamilyNameKey CNContactPhoneticOrganizationNameKey @stuffmc • The Importance of Privacy on iOS 32
  22. Which Properties are accessed? CNContactBirthdayKey CNContactNonGregorianBirthdayKey CNContactNoteKey CNContactImageDataKey CNContactThumbnailImageDataKey CNContactImageDataAvailableKey

    CNContactTypeKey CNContactPhoneNumbersKey CNContactEmailAddressesKey CNContactPostalAddressesKey CNContactDatesKey CNContactUrlAddressesKey CNContactRelationsKey CNContactSocialProfilesKey CNContactInstantMessageAddressesKey @stuffmc • The Importance of Privacy on iOS 33
  23. You don't need to ask permission • Only selecting one

    or more contacts? • Want to see/show which properties you'll give/have? Enter the wonders of... @stuffmc • The Importance of Privacy on iOS 34
  24. ContactsUI let picker = CNContactPickerViewController() picker.delegate = self present(picker, animated:

    true) { // The first time, you might explain // the user he needs to select a contact } func contactPicker(_ picker: CNContactPickerViewController , didSelect contact: CNContact) { } @stuffmc • The Importance of Privacy on iOS 36
  25. Multiple func contactPicker(_ picker: CNCPVC didSelect contacts: [CNContact] ⚠ single

    will be ignored func didSelect contact won't be called @stuffmc • The Importance of Privacy on iOS 37
  26. Contact with Location? // New since iOS 11 CLGeocoder().geocodePostalAddress(CNPostalAddress) {

    ([CLPlacemark]?, Error?) in mapView.addAnnotation (e.g.) }) extension CLPlacemark: MKAnnotation { public var coordinate: CLLocationCoordinate2D { get { return self.location!.coordinate } } } @stuffmc • The Importance of Privacy on iOS 38
  27. Location And MapKit, of course. • No question asked yet

    • Knows I'm in Germany • Not my regional settings • IP Address? @stuffmc • The Importance of Privacy on iOS 39
  28. showsUserLocation • Not doing anything without permission. • No warning

    in Xcode ('s console) either. Bad. • Obviously takes a moment func mapView( _ mapView: MKMapView, didUpdate userLocation: MKUserLocation) { mapView.setCenter(userLocation.coordinate, animated: true) } @stuffmc • The Importance of Privacy on iOS 40
  29. .request*Authorization() WhenInUse / Always let locationManager = CLLocationManager() func viewDidAppear(_

    animated: Bool) { locationManager.requestWhenInUseAuthorization() // or locationManager.requestAlwaysAuthorization() @stuffmc • The Importance of Privacy on iOS 41
  30. The App hasn't crashed App has attempted to access privacy-sensitive

    data w/o a usage description. Info.plist must contain NSLocationWhenInUseUsageDescription with a string explaining to the user how the app uses this data OR ...contain both NSLocationAlwaysAndWhenInUseUsageDescription and NSLocationWhenInUseUsageDescription with string... @stuffmc • The Importance of Privacy on iOS 42
  31. With great power... • Dev: Do you really need access

    to location infos when not using the app? • User: Do you really want this app to know where you are — all time, every time?! • Battery! This would be good for another talk. We as developer are also environmentally responsible of our acts! @stuffmc • The Importance of Privacy on iOS 43
  32. User is asked with 3 options • Only using string

    for AlwaysAndWhenInUse @stuffmc • The Importance of Privacy on iOS 45
  33. Calendar Using NSPredicate? Can't use true for all events predicate

    was not created with EKCalendarStore methods Before asking for permissions, no real crash. [EventKit] Error getting all calendars: Error Domain=EKCADErrorDomain Code=1019 "(null)" [EventKit] Error (1019) in reply block for CADDatabaseFetchCalendarItemsWithPredicate attempt 1/3 [EventKit] Error (1019) in reply block for CADDatabaseFetchCalendarItemsWithPredicate attempt 2/3 [EventKit] Error (1019) in reply block for CADDatabaseFetchCalendarItemsWithPredicate attempt 3/3 [EventKit] All retries exhausted for CADDatabaseFetchCalendarItemsWithPredicate @stuffmc • The Importance of Privacy on iOS 48
  34. requestAccess(to: .event) or Access(to: .reminder) enum EKAuthorizationStatus : Int {

    case notDetermined case restricted case denied case authorized } == PHAuthorizationStatus || CNAuthorizationStatus @stuffmc • The Importance of Privacy on iOS 50
  35. To the next crash ...and beyond Has crashed. Must contain

    an NSCalendarsUsageDescription key with a string. blah blah blah. sh.... @stuffmc • The Importance of Privacy on iOS 51
  36. Access all the calendars? 2 EKCalendar {title = Calendar; type

    = Local; allowsModify = YES; color = #FF1493;} public enum EKCalendarType : Int { case local ... case birthday !!!!!!!!!!!!! } 2 Also case calDAV, case exchange, case subscription @stuffmc • The Importance of Privacy on iOS 52
  37. What have you done? store.predicateForEvents(withStart: Date.distantPast, end: Date.distantFuture, calendars: calendar)

    Like I wanna know everything you did and will do1!, right? Wait, 0 Events? Why? 1 Date.distantPast 0000-12-30 00:00:00 +0000 (Year 0?) Date.distantFuture 4001-01-01 00:00:00 @stuffmc • The Importance of Privacy on iOS 53
  38. What have you done? For performance reasons, this method matches

    only those events within a four year time span. If the date range between startDate and endDate is greater than four years, it is shortened to the first four years. Source: 's Predicate for Events Thanks @michel_fortin on coreint.slack.com @stuffmc • The Importance of Privacy on iOS 54
  39. What have you done? let fourYearsAgo = Date(timeIntervalSinceNow: -60*60*24*365*4) let

    predicate = store.predicateForEvents(withStart: fourYearsAgo, end: Date(), calendars: local) store.events(matching: predicate).forEach { // Now $0 is a single EKEvent print($0.title) } @stuffmc • The Importance of Privacy on iOS 55
  40. Where have you been? ! Need to geocode address string?

    if let l = event.location { CLGeocoder().geocodeAddressString(l) { ! Discover EKStructuredLocation and it's CLLocation property event.structuredLocation?.geoLocation @stuffmc • The Importance of Privacy on iOS 56
  41. Structured Location { title = Lima; address = ; geo

    = <-12.05929000,-77.03006000> +/- 0.00m (speed -1.00 mps / course -1.00) @ 5/27/18, 5:26:17 PM Central European Summer Time; abID = (null); routing = (null); radius = 9178.047384; } @stuffmc • The Importance of Privacy on iOS 57
  42. I'll show you where you were. ... and open the

    URL ... and email all your friends @stuffmc • The Importance of Privacy on iOS 58
  43. You can do so much more EKEvent <0x608000110bc0> { title

    = Hanging Around; location = Lima; calendar = EKCalendar; alarms = (null); URL = ; lastModified = 2018-05-27 14:06:12; startTimeZone = Europe/Berlin; location = Lima; structuredLocation = ...; startDate = 2018-05-23; endDate = 2018-05-23 15:00:00; allDay = 0; floating = 0; recurrence = (null); attendees = (null); travelTime = (null); startLocation = (null); }; @stuffmc • The Importance of Privacy on iOS 59
  44. Know your targets 3 • List of my contacts? attendees

    • (Good or bad) Habits? recurrence 3 I have to play the bad guy... @stuffmc • The Importance of Privacy on iOS 60
  45. EventKitUI • Not like ContactUI • Needs access • No

    link to Settings • Can't see events out of process @stuffmc • The Importance of Privacy on iOS 62
  46. Apps I aim to start • Show developers how to

    use the Privacy APIs • Show users what they should be aware of @stuffmc • The Importance of Privacy on iOS 63