|
// |
|
// SharedWebCredentialsManager.swift |
|
// Keychain |
|
// |
|
// Created by Mohammad Alatrash on 6/14/18. |
|
// |
|
|
|
import Foundation |
|
|
|
enum SharedWebCredentialsManagerError: Error { |
|
case noCredentialsFound |
|
case generatePasswordFailed |
|
case saveFailed(String) |
|
case deleteFailed(String) |
|
} |
|
|
|
class SharedWebCredentialsManager { |
|
|
|
static let shared = SharedWebCredentialsManager() |
|
let domain: String = "www.domain.com" |
|
|
|
func request(_ completion: (String?, String?, SharedWebCredentialsManagerError?) -> Void) { |
|
SecRequestSharedWebCredential(domain as CFString, nil) { (credentials, error) in |
|
guard let credentials = credentials, CFArrayGetCount(credentials) > 0 else { |
|
completion(nil, nil, SharedWebCredentialsManagerError.noCredentialsFound) |
|
return |
|
} |
|
|
|
let credential = CFArrayGetValueAtIndex(credentials, 0) |
|
let credentialDict = unsafeBitCast(credential, to: CFDictionary.self) |
|
let unsafeAccount = CFDictionaryGetValue(credentialDict, Unmanaged.passUnretained(kSecAttrAccount).toOpaque()) |
|
let account = unsafeBitCast(unsafeAccount, to: CFString.self) as String |
|
let unsafePassword = CFDictionaryGetValue(credentialDict, Unmanaged.passUnretained(kSecSharedPassword).toOpaque()) |
|
let password = unsafeBitCast(unsafePassword, to: CFString.self) as String |
|
|
|
completion(account, password, nil) |
|
} |
|
} |
|
|
|
func save(account: String, password: String, completion: ((Bool, SharedWebCredentialsManagerError?) -> Void)? = nil) { |
|
SecAddSharedWebCredential(domain as CFString, account as CFString, password as CFString?) { error in |
|
guard let error = error else { |
|
completion?(true, nil) |
|
return |
|
} |
|
let errorDescription = CFErrorCopyDescription(error) as String |
|
let saveFailedError = SharedWebCredentialsManagerError.saveFailed(errorDescription) |
|
completion?(false, saveFailedError) |
|
} |
|
} |
|
|
|
func delete(account: String, completion: ((Bool, SharedWebCredentialsManagerError?) -> Void)? = nil) -> Promise<Bool> { |
|
SecAddSharedWebCredential(domain as CFString, account as CFString, nil) { error in |
|
guard let error = error else { |
|
completion?(true, nil) |
|
return |
|
} |
|
|
|
let errorDescription = CFErrorCopyDescription(error) as String |
|
let deleteFailedError = SharedWebCredentialsManagerError.saveFailed(errorDescription) |
|
completion?(true, deleteFailedError) |
|
} |
|
} |
|
|
|
func generatePassword(_ completion: ((String?, SharedWebCredentialsManagerError?) -> Void)? = nil) { |
|
guard let password = SecCreateSharedWebCredentialPassword() as String? else { |
|
completion?(nil, SharedWebCredentialsManagerError.generatePasswordFailed) |
|
return |
|
} |
|
completion?(password, nil) |
|
} |
|
} |