vestrel00 / contacts-android

Android Contacts API Library written in Kotlin with Java interoperability. No more ContentProviders and cursors. Say goodbye to ContactsContract. Build your own contacts app!
https://vestrel00.github.io/contacts-android/
Apache License 2.0
601 stars 36 forks source link

Redacted APIs and Entities #147

Closed vestrel00 closed 2 years ago

vestrel00 commented 2 years ago

I have worked on a lot of mobile apps that managed or interacted with user data in some way. In order to protect private user data, we had to "redact" sensitive information when we log stuff in our crash reporting and analytics. User's contacts definitely counts as "private user data" 🤜

There are libraries our there to make redacting easier. For example, https://github.com/ZacSweers/redacted-compiler-plugin However, in spirit of keeping dependencies of this library to a minimum, this library should just provide redacted versions of toString for all of its entities.

I know that we cannot prevent consumers of this API from violating privacy laws if they really want to. BUT, the library should provide consumers an easy way to be GDPR-compliant! This is not necessary for all libraries to implement but this library deals with sensitive, private data. Therefore, we need to be extra careful and provide consumers a GDPR-compliant way to log everything in this library!

Problem

The library APIs and entities do not provide a GDPR-compliant string versions for logging. For example,

fun logContact(contact: Contact) {
    logForAnalytics("NotGDPRCompliant", "Contact: $contact")
}

This will log the contact's email addresses, phone numbers, etc. Output could look like...

NotGDPRCompliant: Contact: id=1, email { address="vestrel00@gmail.com" }, phone { number="(555) 555-5555" }, etc

Solution

Create a "redactable" interface that all APIs and entities must implement. Consumer usage could look like,

fun logContact(contact: Contact) {
    logForAnalytics("GDPRCompliant", "Contact: ${contact.redactedCopy()}")
}

This will redact the contact's email addresses, phone numbers, etc. Output could look like...

GDPRCompliant: Contact: id=1, email { address="*******************" }, phone { number="************" }, etc

Notice that we are simply replacing all characters in the string with "*". This still gives us valuable information such as;

IDs and (typically non-string properties) do not have to be redacted unless they contain sensitive information.

The redactedCopy function should return an actual copy of the entity, except with sensitive data redacted. In addition to logging, this will allow consumers to do cool things like implementing a redacted contact view!

showContactDetails(contact.redactedCopy())

or temporarily redaction!

val contact: Contact
fun onClickRedact() {
    showContactDetails(contact.redactedCopy())
} 

fun onClickUnredact() {
    showContactDetails(contact)
}

FUN STUFF.

Logging redacted stuff in production should be okay, I think. But, I'm not a lawyer so this is NOT legal advice 😁

Checklist

All APIs should be Redactable.

Other stuff to do

Note

This issue is required for;

vestrel00 commented 2 years ago

Included in release; https://github.com/vestrel00/contacts-android/releases/tag/0.1.10