Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save geoff-nixon/b1c74bfb6b00d9569b3d1b2062853e9a to your computer and use it in GitHub Desktop.
Save geoff-nixon/b1c74bfb6b00d9569b3d1b2062853e9a to your computer and use it in GitHub Desktop.
//
// 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)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment