3

Both 1Password and LastPass utilize the same scheme (org-appextension-feature-password-management) for password management. This allows 3rd party apps to use the onepassword-app-extension to work with any of these password managers.

If I want to implement my own password manager which is compatible with this extension, what do I need to do?

Senseful
  • 86,719
  • 67
  • 308
  • 465

1 Answers1

4

To implement a password manager:

  1. Add a new target to your project. Choose "Action Extension."

  2. Add org-appextension-feature-password-management as a URL Scheme (CFBundleURLSchemes) that your app supports.

    You can do this in the Info tab of your target. The scheme is the important part. The identifier doesn't seem to be used.

    This is required so that -[OnePasswordExtension isAppExtensionAvailable] will return true.

  3. In your app extension's target, change the NSExtensionActivationRule from TRUEPREDICATE to the following:

    SUBQUERY (
      extensionItems,
      $extensionItem,
      SUBQUERY (
        $extensionItem.attachments,
        $attachment,
        ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "org.appextension.find-login-action"
      ).@count == $extensionItem.attachments.@count
    ).@count == 1
    

    This will make sure your extension only appears if the -[OnePasswordExtension findLoginForURLString:forViewController:sender:completion:] method is called. If you want to match more than one of these UTIs, see Apple's more complex example here.

    Note: This SUBQUERY is the same as Apple's SUBQUERY example, with the constant changed. If you're wondering about the syntax or how it works, see this answer.

  4. To read which url should be filled:

    let inputItem = extensionContext!.inputItems[0] as! NSExtensionItem
    let inputItemProvider = inputItem.attachments![0] as! NSItemProvider
    
    inputItemProvider.loadItem(forTypeIdentifier: "org.appextension.find-login-action", options: nil) { (data, err) in
        if let err = err { fatalError("\(err)") }
    
        let urlString = (data as! NSDictionary)["url_string"] as! String
    }
    
  5. When you're ready to send data from the extension back to the host app:

    let itemProvider = NSItemProvider(
        item: ["username": "foo", "password": "123"],
        typeIdentifier:kUTTypePropertyList as String) // TODO: import MobileCoreServices
    
    let extensionItem = NSExtensionItem()
    extensionItem.attachments = [itemProvider]
    
    extensionContext!.completeRequestReturningItems([extensionItem], completionHandler: nil)
    

If you're wondering why it's okay to register these schemes, you can read this article:

Our brand-neutral scheme should make things easier both for users and for app developers. Thus, part of our reason for using a brand neutral scheme is to encourage as many app developers as possible to use this scheme. We aren’t forcing app developers to choose between 1Password and some competitor. Instead, we are delegating the choice of which password manager to use to where that choice belongs: you.

Linus Unnebäck
  • 23,234
  • 15
  • 74
  • 89
Senseful
  • 86,719
  • 67
  • 308
  • 465
  • Can you provide more details. There is 19 different Application Extension types, which one is used for creating password manager? – user1478430 Jan 24 '17 at 20:01