iOS App Extension for Password Manager

最近和小伙伴在写一个密码管理app名曰Pass - Passwordstore。为了庆祝App Store上线,打算解决一下issue里两个关于iOS integration/Safari Extension的request (Safari Extension, Integrate it better into iOS)。

Getting Started

首先,我都不知道原来1Password和LastPass可以开启Safari的密码填充。还好提issue的人给了1Password的例子。先附上1Password和LastPass官方关于这个功能(图文并茂)的文档。

简单来说,用法分两步

  • 设:在Safari/Chrome的分享列表里勾上1Password/LastPass
  • 用:在Safari/Chrome/支持的app里的登录页,点Share Icon,选上1Password/LastPass,然后挑选一下列出来的密码

从文档来看,1Password还可以保存密码,这个就先不考虑啦。

接下来问题来了,这到底是咋做到的啊,好奇第点开了1Password这个功能的文档的Learn More: Filling with your approval: On 1Password’s App Extension and iOS 8 security。下面摘录一些我觉得关键的部分吧。

  • Are we really letting third-party apps poke around inside of your 1Password data?
    • Answer: No, that is not how extensions work.
  • Can these third party apps ask 1Password for your PayPal password?
    • Answer: Well, they can ask, but you decide if they should get what they ask for.
  • Can they trick you into entering your 1Password Master Password into something that isn’t 1Password?
    • Answer: The very same mechanisms that prevent that today apply to application extensions.Implementation

恩所以看起来很安全的样子。

下面这张是示意图,以Chrome向1Password要密码为例的话,Host app是Chrome,Containing app是1Password。Host app问App extension要密码,App extension在Containing app里“干点啥”(原文“do stuff”),然后给Host app一个答复(不一定是给密码,也可能是“不告诉你”)。

接下来文档里解释了为什么上面这个流程是安全的,“thanks to a couple of things that are built into the foundation of this system”。下面摘抄几点。

  • Host app不能自己偷偷地向1Password extension问问题:”The host app doesn’t get to decide when it makes a request to an extension. The only time that the host app is able to talk to an extension is when the user—that’s you—asks it to.”

  • 1Password通过shared container给自己的extension共享了点东西,但是共享的内容也是加密的,没有用户的Master Password是解密不能的:”Our extension limits which kinds of requests it takes. The extension, of course, cannot decrypt any of your data unless it is unlocked.”

  • 1Password会让用户确认返回啥给Host app(防止Host app瞎问问题),返回的过程是由OS控制的,比自己复制粘贴更安全。”You have to check that the item you send back is information that you wish to give to the host app. One large advantage of all of this is that, because the operating system is managing this through interprocess communication, the item you select is passed back to the host app in a far more secure manner than the copy-and-paste mechanism this replaces.”

  • 别担心,只要app装对了,打开的extension也一定是对的。”Just as you must explicitly decide which apps you install on your device, you also explicitly decide which extensions you enable. Just as you wouldn’t install an app that masquerades as 1Password, you wouldn’t enable an extension that masquerades as 1Password, even if such apps or extensions were to sneak through Apple’s review process.”

文档的末尾介绍了一下”the scheme of extension selection”,是类似于“http”,“ssh“之类的scheme。

When you install and enable an extension, you say that the particular extension will be the handler for some particular scheme. If (once you get the chance) you install our 1Password extension on iOS, it will be the handler for the schemes org.appextension.find-login-action:, org.appextension.save-login-action:, and org.appextension.fill-webview-action:.

1Password没有用自家域名当scheme而是用了org.appextension.*,是希望这些scheme可以成为通用的scheme,大家可以自行挑选喜欢的password manager,世界上可以有越来越多的password manager任君挑选(我都感动了)。

We created an identifier that is brand and product neutral. This enables developers to simply call the brand neutral org.appextension.* schemes. When you, the user, call on an extension to perform these tasks, you will get your favorite password manager extension; the one you enabled on your device.

The more people using password managers, the better.

Implemnetation

本着1Password美好的”the more the better”愿景,可以开始实现了。先看了几个关于App Extension的Guide/Tutorial。

思路

  • 看完Guide觉得应该用一个Action Extension

  • 从Safari/Chrome给extension URL和HTML,extension列出觉得相关的密码entry,用户选择以后以后,extension努力给填上再返回给Safari/Chrome。填不上的话可以把密码复制到剪贴板,也许得提醒用户自己清一下剪贴板。

  • 从App求密码的时候,得看看1pass是怎么建议开发者索要密码的 https://github.com/AgileBits/onepassword-app-extension 然后就可以准备开始写了,希望周末可以写完。自己挖的坑,哭着也要填完。还得学学JavaScript,哭着填完。