Authenticator icon indicating copy to clipboard operation
Authenticator copied to clipboard

Watch App

Open algesten opened this issue 7 years ago • 13 comments

This is not an issue, but rather wanted to discuss the possibility of adding a watch app.

I've spent some time today familiarising myself with the code. I wanted to get a feeling for what it would take to make a watch app (similar to Authy, but more stylish, like Authenticator).

I wanted to open this issue just to discuss whether you would be interested in such a pull request, and also if you agree on how to achieve it. Basically I think what needs to be done is:

  • Make Base32 framework include watchos arch.
  • Make OneTimePassword include watchos arch.
  • Write token serialisation to NSData in TokenStore (My proof of concept did one that just sends the PersistedToken identifier and the Token URL representation).
  • Put in synchronisation hooks, so every update to TokenStore also triggers a push of the state to the watch.
  • Deserialize the NSData into proper PersistedToken since the OneTimePassword framework will be linked with the watch app as well.
  • Put in pull-hooks so watch app can initiate the state push (on first run for instance).
  • Write a Component with Model/View/Controller for a table overview of tokens.
  • Write a Component with Model/View/Controller for a "Token View" which shows the current token and count down.
  • Use CoreData or something simpler to store the tokens on the watch to allow watch to work without the iPhone in range.

Watch apps are a bit messy with the dual targets (app and extension) and code org, so I'm a bit wary of messing up your nice structure. We need some detailed code reviewing to ensure it's kept nice.

algesten avatar Oct 23 '16 13:10 algesten

Thanks for putting so much thought into this! I'm certainly interested in the possibility of a watch app, but since I don't have an Apple Watch myself, it hasn't been a high priority to me. If you want to take the lead on making it a reality, that would be great!

As I don't have experience developing for the watch, I'm not certain I follow all of the steps above related to push/pull/sync. If the phone were nearby, the app could (I think) request the current password for the current token on demand, but for the app to function without the phone, the watch will need to securely store the tokens on device. Does the watch OS have keychain APIs like iOS does? I'm wary of storing token secrets in CoreData – I'd much prefer to delegate the secure storage of secrets to Apple's own Security framework.

I appreciate that you're thinking about how to add this functionality without complecting the existing app architecture. I'd be more than happy to provide feedback and code reviews if you want to start working on this.

mattrubin avatar Oct 24 '16 03:10 mattrubin

Great!

I googled a bit on keychain on the watch, and it seems that previously you shared keychain with your host app, but now it's a "normal" keychain with icloud sync capabilities (i know you're hesitating to use that, lets keep that discussion out of this thread).

So the plan would be to reuse the entire keychain persistence on the watch and write mehods for storing an entire array of PersistentToken.

that array will be pushed when it changes on the phone, and can be requested from the watch on first run etc.

algesten avatar Oct 24 '16 12:10 algesten

It would be really cool if you could solve this in a way that doesn't require the secrets to be stored on two different devices.

Perhaps the watch could request the one time code from the app instead of generating them itself. The down side is that the watch and phone would need to be near each other, but that is also the up side.

beaucollins avatar Oct 24 '16 18:10 beaucollins

Right now I'm working on using the exact same keychain persistence in the watch app as on the iPhone. I.e. local keychain based (local, as in local to the watch).

It's because I personally would want to use the watch separately from the phone. However making something that requests the code from the phone on-demand, would be trivial, so I don't see why we wouldn't make that an option in the future.

algesten avatar Oct 24 '16 18:10 algesten

Here's a quick work in progress.

entry view entry view

The work is mostly done. Just going to alpha test it myself for a couple of days, and then tidy up my commits.

One thing I did today that I don't know if it is controversial. The syncing between the devices is done using NSData. I decided early on that rather than write some bespoke serialization mechanism, I just use the NSURL representation of the token because I know that will easily be NSData-ified.

Only today did I realise that Token.toURL() produces tokens without the secret so thoroughly that @mattrubin even made test cases to make damn sure the secret is not there. Well. That kinda put my serialization back to square one, so I decided to change that aspect of the OneTimePassword.

I guess the idea may be that secrets go one-way to the keyring and avoid even accidental debugging splip-ups where they leak somewhere in logs or so. Or are there other consequences that I'm unaware of?

algesten avatar Oct 28 '16 16:10 algesten

Pull request is in https://github.com/mattrubin/Authenticator/pull/154

This is probably enough for a first release. Worth to note:

  • It doesn't do HOTP since that would require a round trip to the phone to ensure phone counter is "master". Some work to sort, not that complicated.
  • This version serialises and transmits all tokens every time there's a change on the phone. I've started work to rather transmit delta updates using a new TokenStoreDelegator but we need some refactoring of the store first.
    • The identifier in PersistentToken is the keyring's identifier which means I can't keep those in sync. Could we perhaps instead use a one-way hash from the secret?
    • The relationship Token - PersistentToken complicates things. If we made some simple "random extra properties" that get persisted with the keychain item, we could potentially stick with just Token.
    • (Related to previous) the order is stored separately.
    • Maybe do a toData() serialization of the Token that definitely is allowed to keep the secret and also potential "random extra properties" mentioned above.
  • Bug in that when phone updates the currently viewed token, it doesn't update on the watch. I'm totally lost in the nested view models and enums and can't for my life figure out why. If you go back to the list it is there though.

algesten avatar Oct 29 '16 15:10 algesten

I made the entry screen have the circle countdown animation. Updated the screen grabs above.

algesten avatar Oct 30 '16 11:10 algesten

Seeing that @algesten has released his own authenticator app, is this issue abandoned then? Would very much like to see an official watchOS part of Authenticator.

PatTheMav avatar Oct 19 '17 20:10 PatTheMav

my code is in that PR. it's mostly done. the synchronization may need some love.

algesten avatar Oct 21 '17 11:10 algesten

Thank you for your quick reply @algesten - is Tucan a "fork" of Authenticator (with iCloud Keychain Sync added)?

PatTheMav avatar Oct 21 '17 12:10 PatTheMav

@PatTheMav It's not a fork. It uses some of Matt's excellent OTP code to generate codes on the watch, but the iOS is (for better or worse) written in react native.

It also differs in philosophy around keychain use where it (is supposed to) set flags that allow cross device synchronize on the saved keychain entries. This is to get automatic backup and recovery which comes at a security cost that you may or may not want to pay.

Ultimately there seem to be some bug around the synching so although my app is the one I use, I'm unsure whether I trust that aspect.

algesten avatar Oct 22 '17 14:10 algesten

@mattrubin I would be happy to buy you an Apple Watch if you develop a OTP app for it that syncs with the phone.

haasada avatar Apr 06 '18 17:04 haasada

@mattrubin I will chip in with @haasada to buy you that Watch.

tillydray avatar Feb 21 '19 23:02 tillydray