Implemented storing a default password (but not making use of it yet)

This commit is contained in:
dankito 2020-10-02 04:13:03 +02:00
parent 0f83b2aced
commit b40eb25b70
1 changed files with 68 additions and 3 deletions

View File

@ -1,10 +1,13 @@
import SwiftUI import SwiftUI
import LocalAuthentication
class AuthenticationService { class AuthenticationService {
static private let AuthenticationTypeUserDefaultsKey = "AuthenticationType" static private let AuthenticationTypeUserDefaultsKey = "AuthenticationType"
static private let DefaultPasswordKeychainAccountName = "DefaultPassword"
static private let UserLoginPasswordKeychainAccountName = "UserLoginPassword" static private let UserLoginPasswordKeychainAccountName = "UserLoginPassword"
private let biometricAuthenticationService = BiometricAuthenticationService() private let biometricAuthenticationService = BiometricAuthenticationService()
@ -55,14 +58,19 @@ class AuthenticationService {
setAuthenticationType(.password) setAuthenticationType(.password)
setLoginPassword(newPassword) setLoginPassword(newPassword)
setDefaultPassword(false)
} }
func setAuthenticationMethodToBiometric() { func setAuthenticationMethodToBiometric() {
setAuthenticationType(.biometric) setAuthenticationType(.biometric)
setDefaultPassword(true)
} }
func removeAppProtection() { func removeAppProtection() {
setAuthenticationType(.none) setAuthenticationType(.none)
setDefaultPassword(false)
} }
private func setAuthenticationType(_ type: AuthenticationType) { private func setAuthenticationType(_ type: AuthenticationType) {
@ -73,11 +81,61 @@ class AuthenticationService {
UserDefaults.standard.set(type.rawValue, forKey: Self.AuthenticationTypeUserDefaultsKey) UserDefaults.standard.set(type.rawValue, forKey: Self.AuthenticationTypeUserDefaultsKey)
} }
func setAuthenticationTypeToPassword(_ newPassword: String) {
setAuthenticationType(.password)
setLoginPassword(newPassword) @discardableResult
private func setDefaultPassword(_ useBiometricAuthentication: Bool) -> Bool {
do {
let passwordItem = createDefaultPasswordKeychainItem(useBiometricAuthentication)
let currentPassword = try? passwordItem.readPassword()
try? passwordItem.deleteItem()
if let currentPassword = currentPassword {
try passwordItem.savePassword(currentPassword)
} }
else {
createNewDefaultPassword(useBiometricAuthentication)
}
return true
} catch {
NSLog("Could not save default password: \(error)")
}
return false
}
private func createNewDefaultPassword(_ useBiometricAuthentication: Bool) {
do {
let newDefaultPassword = generateRandomPassword(30)
let passwordItem = createDefaultPasswordKeychainItem(useBiometricAuthentication)
try passwordItem.savePassword(newDefaultPassword)
} catch {
NSLog("Could not create new default password: \(error)")
}
}
private func createDefaultPasswordKeychainItem(_ useBiometricAuthentication: Bool) -> KeychainPasswordItem {
var accessControl: SecAccessControl? = nil
var context: LAContext? = nil
if useBiometricAuthentication {
accessControl = SecAccessControlCreateWithFlags(nil, // Use the default allocator.
kSecAttrAccessibleWhenUnlocked,
.userPresence,
nil) // Ignore any error.
// TODO: this does not work yet, setting LAContext results in a "unexpectedPasswordData" error
// context = LAContext()
// context?.touchIDAuthenticationAllowableReuseDuration = 45
}
return KeychainPasswordItem(service: Self.DefaultPasswordKeychainAccountName, account: nil, accessGroup: nil, secAccessControl: accessControl, authenticationContext: context)
}
@discardableResult @discardableResult
private func setLoginPassword(_ newPassword: String) -> Bool { private func setLoginPassword(_ newPassword: String) -> Bool {
@ -139,4 +197,11 @@ class AuthenticationService {
} }
} }
private func generateRandomPassword(_ passwordLength: Int) -> String {
let dictionary = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789§±!@#$%^&*-_=+;:|/?.>,<"
return String((0 ..< passwordLength).map{ _ in dictionary.randomElement()! })
}
} }