Last active
September 5, 2019 06:44
-
-
Save rafaelbartolome/0b433b8e95ea08ef596a114e6c3a575e to your computer and use it in GitHub Desktop.
Use iCloud SafariKeychain from Swift5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// SafariKeychain.swift | |
// Positipp | |
// | |
// Created by Rafael Bartolome on 15/06/2019. | |
// Copyright © 2019 Moonshot People Tech SL. All rights reserved. | |
// | |
import Foundation | |
extension String: Error {} | |
typealias SafariKeychainCheckCompletion = (Result<(String?, String?), Error>) -> Void | |
typealias SafariKeychainUpdateCompletion = (Result<Void, Error>) -> Void | |
class SafariKeychain { | |
enum Constants { | |
/// Error code for when there are no accounts associated with the domain | |
static let SafariKeychainErrorCodeNoAccount = -25300 | |
/// Error code for when the entitlements aren't setup correctly. | |
static let SafariKeychainErrorCodeNoDomain = -50 | |
#warning("TODO: Update domain to your domain") | |
static let Domain = "example.com" | |
} | |
} | |
extension SafariKeychain { | |
/// Request the credentials information stored in safari keychain | |
func checkSafariCredentials(completion: @escaping SafariKeychainCheckCompletion) { | |
SecRequestSharedWebCredential(Constants.Domain as CFString?, .none) { (credentials, error) -> () in | |
var username: String? | |
var password: String? | |
if let error = error { | |
return completion(.failure(error)) | |
} | |
if let credentials = credentials { | |
let credentialsArray = credentials as NSArray | |
if credentialsArray.count > 0 { | |
if let credentials = credentialsArray[0] as? [String: String] { | |
if let account = credentials[String(kSecAttrAccount)] { | |
username = account | |
} | |
if let sharedPassword = credentials[String(kSecSharedPassword)] { | |
password = sharedPassword | |
} | |
DispatchQueue.main.async { | |
completion(.success((username, password))) | |
} | |
return | |
} | |
} | |
} else { | |
//User cancelled the operation | |
DispatchQueue.main.async { | |
completion(.failure("User cancel operation")) | |
} | |
return | |
} | |
DispatchQueue.main.async { | |
completion(.failure("General error")) | |
} | |
} | |
} | |
/// Update the credentials information in safari keychain or remove the current ones by passing a nil password. | |
func updateSafariCredentials(userName: String, | |
password: String? = nil, | |
completion: @escaping SafariKeychainUpdateCompletion) { | |
SecAddSharedWebCredential(Constants.Domain as CFString, userName as CFString, password as CFString?) { error -> () in | |
if let error = error { | |
completion(.failure(error)) | |
} else { | |
completion(.success(())) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you so much Rafael