realm / realm-tasks

To Do app built with Realm, inspired by Clear for iOS
Other
369 stars 71 forks source link

CloudKit Seamless Authentication Between User Devices #10

Open TimOliver opened 8 years ago

TimOliver commented 8 years ago

One of the overarching goals of this app is to consider each aspect of the experience from the user's perspective. Obviously, one of the more challenging aspects of Sync is coming up with a pattern where Sync is able to determine all of the devices a user owns (And would like their content sync'd to), with as little interaction on the user's behalf, and certainly avoiding requiring private information (Like email addresses).

In the actual Clear app, activating sync via iCloud is a simple as a single tap in the Settings dialog: clearsync

This is the bar we should aim for, as anything lower than this would obviously be an inferior experience for the user.

An interesting article discovered by @astigsen shows a really good way of achieving this: https://medium.com/@skreutzb/ios-onboarding-without-signup-screens-cb7a76d01d6e#.rpxuwq3ke

The idea is to use CloudKit as a seamless authentication layer in order to identify users via their iCloud account, but still maintaining a complete level of anonymity without directly requiring their account credentials.

In a nutshell, CloudKit provides each app with a token that is unique for that user and their Apple ID, guaranteed to be the same for the app running on each of their devices.

In this way, it would simply be a matter of requesting this iCloud token on initial launch of the app, and then using it as the user identity value for Realm Sync.

From the user perspective, this would appear completely seamless and automatic.

bigfish24 commented 8 years ago

@TimOliver note to support CloudKit this isn't just a client-side implementation. The user management/authentication of the sync server is evolving beyond the primitive handling currently available, here's the general overview per @simonask:

The client app acquires an access token from a third-party (Facebook support is included in this PR). This token is passed to an API in the binding (see realm/realm-cocoa-private#142). The authentication server (implemented in Node.js, see auth/server.js) validates the Facebook token and issues a Realm access token if it is valid. This is passed back to the client. The Sync server receives the Realm access token and initiates synchronization if it is valid.

This means that to support CloudKit or any other authentication scheme, the authentication server needs to be updated to validate the incoming token. I believe this is the HTTP GET call that can be used.

cc @jpsim

bigfish24 commented 8 years ago

@TimOliver do you want to tackle updating the Node.js script similar to what @simonask did for FB seen in this PR. We would then need to update the binding API as well to support a CloudKit option.

More generally, Simon's client API PR hasn't been reviewed so I think @jpsim and others should review.

TimOliver commented 8 years ago

@bigfish24 Oh okay! I wasn't up to speed on the direction Sync's auth pipeline was headed. Sure! I'll take a look at that Facebook support class and see what is needed to make one for CloudKit authentication.

TimOliver commented 8 years ago

Just did a bit of extra digging. It looks like CloudKit allows external web servers to authenticate against it using a token exchange REST API. It should be relatively trivial to duplicate the Facebook auth code for this one. I'll leave this here for future reference.

https://developer.apple.com/library/ios/documentation/DataManagement/Conceptual/CloutKitWebServicesReference/SettingUpWebServices/SettingUpWebServices.html#//apple_ref/doc/uid/TP40015240-CH24-SW2

jpsim commented 8 years ago

@TimOliver as discussed in our 1 on 1 just now, let's focus on getting sync working well with user interactions at the moment. Building strong authentication mechanisms is high on the priority list but is being worked on by @austinzheng in realm/realm-cocoa-private#145 & realm/realm-cocoa-private#156.