I'm using sskeychain (https://github.com/soffes/sskeychain) to store my accounts and passwords in the IOS keychain. I assume, that if I store an account, it should be available on my other device. But it doesn't appear there.
I read my accounts with this code:
NSArray *arr=[SSKeychain accountsForService:@"Login"];
for (NSString *s in arr) {
NSLog(@"Account: %@",s);
}
and get this (only shown one entry, the others are similar):
Account: {
acct = "friXXXXXter@XXXX.com";
agrp = "3B4384Z34A.de.gondomir.LocalButler";
cdat = "2014-05-09 22:55:08 +0000";
mdat = "2014-05-09 22:55:08 +0000";
pdmn = ak;
svce = Login;
sync = 0;
tomb = 0;
}
But this doesn't appear on the other device. Both devices have IOS 7.1.1.
I store the password with this line:
[SSKeychain setPassword:self.passwortField.text forService:@"Login" account:self.userField.text];
I have switched on keychain sharing in Xcode and have a keychain group "de.gondomir.LocalButler" listed there.
Am I missing something? Must the service name something special?
Thanks!
In case this is still relevant for you I managed to find the solution. (works for >=iOS7)
Don't use the static methods of SSKeychain to write your credentials. Instead use SSKeychainQuery
and set the synchronizationMode to SSKeychainQuerySynchronizationModeYes
like this
NSError *error;
[SSKeychain setAccessibilityType:self.keychainAccessibilityType];
SSKeychainQuery *query = [[SSKeychainQuery alloc] init];
query.service = service;
query.account = account;
query.password = password;
query.synchronizationMode = SSKeychainQuerySynchronizationModeYes;
[query save:&error];
if (error) {
NSLog(@"Error writing credentials %@", [error description]);
}
The static convenience methods on SSKeychain
use the default synchronization mode SSKeychainQuerySynchronizationModeAny
causing credentials not to be synchronized with the iCloud keychain.
Additionally, make sure your devices have Keychain via iCloud enabled (Settings>iCloud>Keychain). You might also want to enable Keychain Sharing
in your targets Capabilities.
After I have a new project I tried the answer of MarkHim, it works.
I used swift now, so here is my working code:
let account = defaults.objectForKey("Sync_toPhoneNumber") as? String
SSKeychain.setAccessibilityType(kSecAttrAccessibleAfterFirstUnlock)
var error:NSError?
let lookupQuery = SSKeychainQuery()
lookupQuery.synchronizationMode = .Yes
lookupQuery.service = "DasDing"
lookupQuery.account = account
let password = SSKeychain.passwordForService("DasDing", account: account, error: &error)
if error == nil {
commandKey = password!
} else {
print("Error für \(account): \(error!.localizedDescription)")
commandKey = ""
}
// query all accounts for later use
let allQuery = SSKeychainQuery()
allQuery.service = "DasDing"
do {
let dict = try allQuery.fetchAll()
print("Accounts:")
for acc in dict {
print(acc["acct"]!)
}
} catch let error as NSError {
print("keine Accounts")
print("Error: \(error.localizedDescription)")
}
That's for reading, for writing you must delete the account first (if you want to change the password):
let account = defaults.objectForKey("Sync_toPhoneNumber") as? String
SSKeychain.setAccessibilityType(kSecAttrAccessibleAfterFirstUnlock)
SSKeychain.deletePasswordForService("DasDing", account: account)
let newQuery = SSKeychainQuery()
newQuery.service = "DasDing"
newQuery.account = account
newQuery.password = str?.uppercaseString
newQuery.synchronizationMode = .Yes
try! newQuery.save()