Password Manager App Extension written in Swift
Users of your app will be able to:
- Use their password manager to retrieve their credentials for your login screen.
- Create new login information with a strong password generator and save to their password manager.
- Change their password without leaving your app.
You can install Carthage with Homebrew using the following command:
brew update
brew install carthage
To integrate JSONFeed into your Xcode project using Carthage, specify it in your Cartfile
where "x.x.x"
is the current release:
github "TaniaGoswami/PasswordManager" "x.x.x"
To install using Swift Package Manager have your Swift package set up, and add PasswordManager as a dependency to your Package.swift
.
dependencies: [
.Package(url: "https://github.com/TaniaGoswami/PasswordManager.git", majorVersion: 0)
]
Add all the files from PasswordManager/PasswordManager
to your project
Check if a password management application is available with the isPasswordManagerAvailable
variable. If it is, show login icon so that the user is aware that they can use their password manager to log in.
Add org-appextension-feature-password-management
to your target's info.plist
:
Call the findLogin
method from your UIViewController
when the button is clicked. This is what the call and result handling could look like:
PasswordManager.shared.findLogin(urlString: "https://www.yourapp.com", viewController: self, sender: self.passwordButton) { dictionary, error in
if let error = error {
result(nil, nil, error)
return
}
guard let username = dictionary?["username"] as? String else {
result(nil, nil, PasswordManagerError.usernameNotFound)
return
}
guard let password = dictionary?["password"] as? String else {
result(nil, nil, PasswordManagerError.passwordNotFound)
return
}
result(username, password, nil)
}
The share sheet will be presented on the UIViewController that is passed in. The completion block will be called on the main thread when the user finishes their selection. Finally, you can retrieve the credentials from the login dictionary and validate them.
Call the storeLogin
method from your UIViewController
when the create account button is clicked. This is what the call and result handling could look like:
func createLogin(username: String, password: String, viewController: UIViewController, sender: UIView, result: @escaping (String?, String?, Error?) -> Void) {
let newLoginDetails: [String : Any] = [
"login_title": "Your App",
"username": username,
"password": password,
"notes": "Saved with your app"
]
let passwordGenerationOptions: [String: Any] = ["password_min_length": 8 ]
PasswordManager.shared.storeLogin(urlString: "https://www.yourapp.com", loginDetails: newLoginDetails, passwordGenerationOptions: passwordGenerationOptions, viewController: viewController, sender: sender) { dictionary, error in
if let error = error {
result(nil, nil, error)
return
}
guard let username = dictionary?["username"] as? String else {
result(nil, nil, PasswordManagerError.usernameNotFound)
return
}
guard let password = dictionary?["password"] as? String else {
result(nil, nil, PasswordManagerError.passwordNotFound)
return
}
result(username, password, nil)
}
}
Remember that your value for urlString
here should be the same as it was in your findLogin
command so that users can later use the login information that they generated.
Call the changePassword
method from your UIViewController
for your change password screen. This is what the call and result handling could look like:
func changePassword(username: String, oldPassword: String, password: String, viewController: UIViewController, sender: UIView, result: @escaping (String?, String?, String?, Error?) -> Void) {
let updateCredentialsDetails: [String : Any] = [
"login_title": "Your App",
"username": username,
"old_password": oldPassword,
"password": password,
"notes": "Saved with your app"
]
let passwordGenerationOptions: [String: Any] = ["password_min_length": 8 ]
PasswordManager.shared.changePasswordForLogin(urlString: "https://www.yourapp.com", loginDetails: updateCredentialsDetails, passwordGenerationOptions: passwordGenerationOptions, viewController: viewController, sender: sender) { dictionary, error in
if let error = error {
result(nil, nil, nil, error)
return
}
guard let username = dictionary?["username"] as? String else {
result(nil, nil, nil, PasswordManagerError.usernameNotFound)
return
}
guard let password = dictionary?["password"] as? String else {
result(nil, nil, nil, PasswordManagerError.passwordNotFound)
return
}
guard let oldPassword = dictionary?["old_password"] as? String else {
result(nil, nil, nil, PasswordManagerError.passwordNotFound)
return
}
result(username, password, oldPassword, nil)
}
}
Remember that your value for urlString
here should be the same as it was in your findLogin
command so that users can later use the login information that they generated.
URLString
should refer to your service so that your user can find their login information within their password manager app. If you don't have a website for your app, you should use your bundle identifier for theURLString
:app://yourapp
.