diff --git a/App/Info.plist b/App/Info.plist
index 8a0e393bf..d6499c492 100644
--- a/App/Info.plist
+++ b/App/Info.plist
@@ -33,6 +33,10 @@
CFBundleVersion
1
+ LSApplicationQueriesSchemes
+
+ org-appextension-feature-password-management
+
LSRequiresIPhoneOS
UILaunchStoryboardName
@@ -50,9 +54,5 @@
UIInterfaceOrientationLandscapeRight
UIInterfaceOrientationPortraitUpsideDown
- LSApplicationQueriesSchemes
-
- org-appextension-feature-password-management
-
diff --git a/App/ViewController.swift b/App/ViewController.swift
index 6ebda384b..8d49b522b 100644
--- a/App/ViewController.swift
+++ b/App/ViewController.swift
@@ -50,6 +50,7 @@ class ViewController: UIViewController {
.classic()
.withOptions {
applyDefaultOptions(&$0)
+ $0.passwordManager = PasswordManagerConfig(appIdentifier: "www.myapp.com", displayName: "My App")
$0.customSignupFields = [
CustomTextField(name: "first_name", placeholder: "First Name", icon: LazyImage(name: "ic_person", bundle: Lock.bundle)),
CustomTextField(name: "last_name", placeholder: "Last Name", icon: LazyImage(name: "ic_person", bundle: Lock.bundle))
diff --git a/Lock/ClassicRouter.swift b/Lock/ClassicRouter.swift
index 595163715..2532b27c7 100644
--- a/Lock/ClassicRouter.swift
+++ b/Lock/ClassicRouter.swift
@@ -52,8 +52,8 @@ struct ClassicRouter: Router {
let authentication = self.lock.authentication
let interactor = DatabaseInteractor(connection: database, authentication: authentication, user: self.user, options: self.lock.options, dispatcher: lock.observerStore)
let presenter = DatabasePresenter(interactor: interactor, connection: database, navigator: self, options: self.lock.options)
- if self.lock.options.showPasswordManager, OnePassword.isAvailable() {
- let passwordManager = OnePassword(identifier: self.lock.options.passwordManagerAppIdentifier, controller: self.controller)
+ if self.lock.options.passwordManager.isEnabled, OnePassword.isAvailable() {
+ let passwordManager = OnePassword(withConfig: self.lock.options.passwordManager, controller: self.controller)
presenter.passwordManager = passwordManager
}
if !oauth2.isEmpty {
diff --git a/Lock/IconButton.swift b/Lock/IconButton.swift
index 1b0694d22..ec6505966 100644
--- a/Lock/IconButton.swift
+++ b/Lock/IconButton.swift
@@ -59,7 +59,6 @@ class IconButton: UIView {
private func layoutButton() {
let button = UIButton(type: .custom)
-
self.addSubview(button)
constraintEqual(anchor: button.topAnchor, toAnchor: self.topAnchor)
@@ -69,7 +68,6 @@ class IconButton: UIView {
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget(self, action: #selector(pressed), for: .touchUpInside)
-
self.button = button
}
diff --git a/Lock/LockOptions.swift b/Lock/LockOptions.swift
index 0472ddf5e..7be2b58f8 100644
--- a/Lock/LockOptions.swift
+++ b/Lock/LockOptions.swift
@@ -47,7 +47,5 @@ struct LockOptions: OptionBuildable {
var audience: String?
var passwordlessMethod: PasswordlessMethod = .code
-
- var showPasswordManager: Bool = true
- var passwordManagerAppIdentifier: String = Bundle.main.bundleIdentifier!
+ var passwordManager: PasswordManagerConfig = PasswordManagerConfig()
}
diff --git a/Lock/OnePassword.swift b/Lock/OnePassword.swift
index c1939b443..f5d3f5b84 100644
--- a/Lock/OnePassword.swift
+++ b/Lock/OnePassword.swift
@@ -32,12 +32,12 @@ protocol PasswordManager {
class OnePassword: PasswordManager {
- let identifier: String
+ let config: PasswordManagerConfig
weak var controller: UIViewController?
var fields: [String: InputField] = [:]
- required init(identifier: String, controller: UIViewController?) {
- self.identifier = identifier
+ required init(withConfig config: PasswordManagerConfig, controller: UIViewController?) {
+ self.config = config
self.controller = controller
}
@@ -47,7 +47,7 @@ class OnePassword: PasswordManager {
func login(callback: @escaping (Error?, [String: InputField]?) -> Void) {
guard let controller = self.controller else { return }
- LockOnePasswordExtension.shared().findLogin(forURLString: self.identifier, for: controller, sender: nil) { (result, error) in
+ LockOnePasswordExtension.shared().findLogin(forURLString: self.config.appIdentifier, for: controller, sender: nil) { (result, error) in
guard error == nil else {
return callback(error, nil)
}
@@ -58,10 +58,10 @@ class OnePassword: PasswordManager {
}
func store(withPolicy policy: [String: Any]?, callback: @escaping (Error?, [String: InputField]?) -> Void) {
- guard let displayName = Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String, let controller = self.controller else { return }
- var loginDetails: [String: String] = [ AppExtensionTitleKey: displayName ]
+ guard let controller = self.controller else { return }
+ var loginDetails: [String: String] = [ AppExtensionTitleKey: self.config.displayName ]
self.fields.forEach { loginDetails[$0] = $1.text }
- LockOnePasswordExtension.shared().storeLogin(forURLString: self.identifier, loginDetails: loginDetails, passwordGenerationOptions: policy, for: controller, sender: nil) { (result, error) in
+ LockOnePasswordExtension.shared().storeLogin(forURLString: self.config.appIdentifier, loginDetails: loginDetails, passwordGenerationOptions: policy, for: controller, sender: nil) { (result, error) in
guard error == nil else {
return callback(error, nil)
}
@@ -71,3 +71,19 @@ class OnePassword: PasswordManager {
}
}
}
+
+public struct PasswordManagerConfig {
+ public var isEnabled: Bool = true
+ public let appIdentifier: String
+ public let displayName: String
+
+ public init() {
+ self.appIdentifier = Bundle.main.bundleIdentifier!
+ self.displayName = Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as! String
+ }
+
+ public init(appIdentifier: String, displayName: String) {
+ self.appIdentifier = appIdentifier
+ self.displayName = displayName
+ }
+}
diff --git a/Lock/OptionBuildable.swift b/Lock/OptionBuildable.swift
index 4d6977a0c..593e87266 100644
--- a/Lock/OptionBuildable.swift
+++ b/Lock/OptionBuildable.swift
@@ -91,11 +91,8 @@ public protocol OptionBuildable: Options {
/// Specify the passwordless method, send a passcode or magic link. By default is .code
var passwordlessMethod: PasswordlessMethod { get set }
- /// Show password manager button when user credentials are needed, e.g. during Sign Up, and allow storing/retrieving credentials from the password manager. By default is true
- var showPasswordManager: Bool { get set }
-
- /// Application identifier used by the password manager, if you also have a web app we recommend adding your site url. By default is the application bundle identifier
- var passwordManagerAppIdentifier: String { get set }
+ /// Configuration to be used by the password manager.
+ var passwordManager: PasswordManagerConfig { get set }
}
extension OptionBuildable {
diff --git a/Lock/Options.swift b/Lock/Options.swift
index 2e80f018d..e11da7fea 100644
--- a/Lock/Options.swift
+++ b/Lock/Options.swift
@@ -49,7 +49,5 @@ public protocol Options {
var audience: String? { get }
var passwordlessMethod: PasswordlessMethod { get }
-
- var showPasswordManager: Bool { get }
- var passwordManagerAppIdentifier: String { get }
+ var passwordManager: PasswordManagerConfig { get }
}
diff --git a/LockTests/OnePasswordSpec.swift b/LockTests/OnePasswordSpec.swift
index 144134776..ff4d504d3 100644
--- a/LockTests/OnePasswordSpec.swift
+++ b/LockTests/OnePasswordSpec.swift
@@ -31,6 +31,7 @@ class OnePasswordSpec: QuickSpec {
var onePassword: OnePassword?
var viewController: MockViewController?
+ var passwordConfig: PasswordManagerConfig!
describe("availability") {
@@ -45,16 +46,18 @@ class OnePasswordSpec: QuickSpec {
beforeEach {
onePassword = nil
viewController = MockViewController()
+ passwordConfig = PasswordManagerConfig()
}
- it("should init with identifier") {
- onePassword = OnePassword(identifier: "www.mysite.com", controller: nil)
- expect(onePassword?.identifier) == "www.mysite.com"
+ it("should init with default config") {
+ onePassword = OnePassword(withConfig: passwordConfig, controller: nil)
+ expect(onePassword?.config.appIdentifier) == Bundle.main.bundleIdentifier!
+ expect(onePassword?.config.displayName) == Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String
+ expect(onePassword?.config.isEnabled) == true
}
it("should init with identifier and controller") {
- onePassword = OnePassword(identifier: "www.mysite.com", controller: viewController)
- expect(onePassword?.identifier) == "www.mysite.com"
+ onePassword = OnePassword(withConfig: passwordConfig, controller: viewController)
expect(onePassword?.controller).to(equal(viewController))
}
@@ -64,7 +67,8 @@ class OnePasswordSpec: QuickSpec {
beforeEach {
viewController = MockViewController()
- onePassword = OnePassword(identifier: "www.mysite.com", controller: viewController)
+ passwordConfig = PasswordManagerConfig()
+ onePassword = OnePassword(withConfig: passwordConfig, controller: viewController)
}
it("should present extension prompt on login") {
diff --git a/LockTests/OptionsSpec.swift b/LockTests/OptionsSpec.swift
index 2691f3fc2..1259c6077 100644
--- a/LockTests/OptionsSpec.swift
+++ b/LockTests/OptionsSpec.swift
@@ -98,14 +98,17 @@ class OptionsSpec: QuickSpec {
expect(options.passwordlessMethod).to(equal(PasswordlessMethod.code))
}
- it("should show passwordManager") {
- expect(options.showPasswordManager) == true
+ it("should have passwordManager enabled") {
+ expect(options.passwordManager.isEnabled) == true
}
- it("should match bundler identifier") {
- expect(options.passwordManagerAppIdentifier) == Bundle.main.bundleIdentifier
+ it("should have passwordManager app bundler identifier") {
+ expect(options.passwordManager.appIdentifier) == Bundle.main.bundleIdentifier!
}
+ it("should have passwordManager app display name") {
+ expect(options.passwordManager.displayName) == Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String
+ }
}
describe("validation") {
diff --git a/README.md b/README.md
index 03c340ca3..166186504 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@ Need help migrating from v1? Please check our [Migration Guide](MIGRATION.md)
Add the following line to your Podfile:
```ruby
- pod "Lock", "~> 2.1.0"
+ pod "Lock", "~> 2.1"
```
### Carthage
@@ -37,7 +37,7 @@ Need help migrating from v1? Please check our [Migration Guide](MIGRATION.md)
In your `Cartfile` add
```ruby
-github "auth0/Lock.swift" ~>2.1.0
+github "auth0/Lock.swift" ~> 2.1
```
## Usage
@@ -361,25 +361,25 @@ When signing up the default information requirements are the user's *email* and
*Note: You must specify the icon to use with your custom text field and store it in your App's bundle.*
-#### 1Password
+#### Password Manager
-By default 1Password support is enabled, although you will still need to have the 1Password app installed for the option to be visible in the login and signup screens. You can disable 1Password support using the `showPasswordManager` option.
+By default password manager support using [1Password](https://1password.com/) is enabled for database connections, although you will still need to have the 1Password app installed for the option to be visible in the login and signup screens. You can disable 1Password support using the `isEnabled` property of the `passwordManager`.
```swift
.withOptions {
- $0.showPasswordManager = false
+ $0.passwordManager.isEnabled = false
}
```
-By default the `passwordManagerAppIdentifier` will be set to the app bundle identifier. If you need to share credentials with your website that also uses the same Auth0 connection, then you can use name of the website e.g.
+By default the `appIdentifier` will be set to the app's bundle identifier and the `displayName` will be set to the app's display name. You can customize this as follows:
```swift
.withOptions {
- $0.passwordManagerAppIdentifier = "www.website.com"
+ $0.passwordManager = PasswordManagerConfig(appIdentifier: "www.myapp.com", displayName: "My App")
}
```
-You will also need to add the following to your app's `info.plist`:
+You will need to add the following to your app's `info.plist`:
```xml
LSApplicationQueriesSchemes