iOS Keychain Value Nil - ios

I'm using this iOS library to handle storing and getting values in the iOS Keychain. Below is the main code I'm using to store a value in the keychain.
let email: String = emailTextField.text!
let keychain = KeychainSwift()
keychain.set(email, forKey: "email")
I'm trying to set values in the keychain to store the users email and password. The code above is only for email. Right after that code I have set a breakpoint and running p keychain.get("email") returns nil in the console. p keychain.lastResultCode returns -25300. Even after trying to quit the app and get the data again it still doesn't seem to be working. Any ideas why it would be returning nil? Just for reference I'm using the iPhone Simulator running Xcode 8.

You have to turn on Keychain Sharing capability in order for the simulator to work.
This seems to be a known bug. You can read up more on here.
https://forums.developer.apple.com/message/179846

Related

How to fix "http not found in com.apple.developer.associated-domains entitlement" in iOS app?

I have created a basic iOS app in Swift that uses a WKWebView. I am using SecAddSharedWebCredential and SecRequestSharedWebCredential to save and load usernames and passwords within the users KeyChain.
When I launch the app with the simulator, everything works perfectly fine. Although, when I launch on a device, I get the error of:
http not found in com.apple.developer.associated-domains entitlement
Within the simulator and device, when displaying the credential list to a user, it comes up as (note the http):
When using my save and get functions, I make sure that I pass in my URL, so I don't think that could be the problem.
SecAddSharedWebCredential(self.URLPath, loginUsername, loginPassword)
SecRequestSharedWebCredential(self.URLPath, nil)
It looks like you have something like webcredentials:http://example.com in your entitlements. Try getting rid of the http so it's just webcredentials:example.com.

Keychain access on watchOS 2 not working on the actual watch

I have read in the Apple developer forum that unlike watchOS 1, watchOS 2 does not share its keychain with the phone app so bam!! keychain sharing is not enabled by default we got to do a workaround for that.
Ok coming to my issue, I was trying to run a very basic keychain access program on the actual watch device running the latest beta (beta4) using a git library https://github.com/jrendel/SwiftKeychainWrapper
let saveSuccessful: Bool = KeychainWrapper.setString("keychainData", forKey: "ImportantKeychainData")
if saveSuccessful{
let retrievedString: String? = KeychainWrapper.stringForKey("ImportantKeychainData")
print(retrievedString)
}
else
{
print("unable to write keychain data")
}
On the simulator it works like a charm but when I try to run the same on the actual watch it gives me an status code of -34018
There was no public documentation about this error code but I did a little digging to find out it turned out to be
errSecMissingEntitlement = -34018, /* Internal error when a required entitlement isn't present. */
source: http://opensource.apple.com/source/Security/Security-55471/sec/Security/SecBasePriv.h
I did a lot of research actually a full day on this and people pointed me to various directions, like memory issues, entitlements, profile issue, bug in keychain etc.
The catch here is that most of the dev's who reported this issue did not have it continuously like I got it on every run of the app, they had it at certain places only like when app was in background etc. To summarise,
1. I tried the same piece of code on iOS 9 beta 4 and it worked well on the phone.
2. The same code works well on the watch simulator.
3. The same code does not work on watchOS beta 4 returns -34018 continuously on the device but works well on the simulator.
4. All this testing is done using free provisioning introduced from Xcode 7, entitlements were added to the phone app and the watch extension, keychain sharing was enabled, app groups was enabled.
My questions are
1. Am I missing something here that I have to do with the device keychain that I am supposedly doing it wrong?
2. Is there an issue with free provisioning?
3. Is there an issue with the keychain perhaps??
Any help is appreciated.
FYI I also tried Apple's KeychainItemWrapper, customs code directly talking to SecItem methods nothing turned out to be fruitful.
Update, I tried this as well it fails as usual
let storableString:NSString = "keychain in watchos is working with simple code"
let query : [NSString : AnyObject] = [
kSecClass : kSecClassGenericPassword,
kSecAttrService : "WatchService",
kSecAttrLabel : "KeychainData",
kSecAttrAccount : "SecureData",
kSecValueData : storableString.dataUsingEncoding(NSUTF8StringEncoding)!
]
let result = SecItemAdd(query, nil)
print(result)
Update 2: Issue has been fixed in watchOS2 beta 5.
Issue has been fixed by Apple in the recent watchOS 2 beta 5.

iOS Keychain writing value results in error code -34018

I have an iOS application that stores some sensitive information in the keychain.
While writing values into the keychain, I am getting error code -34018.
I am currently using Apple's iOS KeyChainItemWrapper class.
Both of the following lines of code receive the same error code.
OSStatus res1 = SecItemCopyMatching((__bridge CFDictionaryRef)genericPasswordQuery, (CFTypeRef *)&attributes);
OSStatus res = SecItemUpdate((__bridge CFDictionaryRef)updateItem, (__bridge CFDictionaryRef)tempCheck);
This issue does not occur every time, but intermittently. Once I get this error, I am no longer able to write any values to the keychain.
I have printed the error description like so:
NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:res userInfo:nil];
and this is what the error prints out:
Error: Error Domain=NSOSStatusErrorDomain Code=-34018 "The operation couldn’t be completed. (OSStatus error -34018.)"
Seems like this is a bug in Keychain, which only appears when you launch your app from xcode. See here: https://github.com/soffes/sskeychain/issues/52
We debugged it a lot and it seems an issue accessing the keychain when
the app is launched from the background. This is only happening with
the debugger (i.e. when launched from Xcode). We think the issue
might be related in our case to the debugger keeping alive the app
even if it should be killed by the OS. We tried in fact to run the
app and then put it in background and launch many other app to occupy
RAM. With the debugger the bug came up when resuming the app from the
background, while without the debugger it didn't (we did run at least
10 tests each).
If someone will come here back with this error and XCode8 with iOS10, probably you have to enable KeyChain Share in the tab Capabilities:
As others have mentioned, this is a Keychain bug, one that Apple is aware of and has been aware of since at least mid-2015.
As of March 22, 2016, however, Apple has said:
We believe these problems were resolved in iOS 9.3.
iOS 9.3 was released on March 21, 2016.
See the thread: https://forums.developer.apple.com/thread/4743
To quote the response by an Apple employee:
Mar 22, 2016 3:28 AM
OK, here’s the latest. This is a complex problem with multiple possible causes:
Some instances of the problem are caused by incorrect app signing. You can easily distinguish this case because the problem is 100% reproducible.
Some instances of the problem are caused by a bug in how iOS supports app development (r. 23,991,853). Debugging this was complicated by the fact that another bug in the OS (r. 23,770,418) masked its effect, meaning the problem only cropped up when the device was under memory pressure.
We believe these problems were resolved in iOS 9.3.
We suspect that there may be yet more causes of this problem.
So, if you see this problem on a user device (one that hasn’t been talked to by Xcode) that’s running iOS 9.3 or later, please do file a bug report about it. Try to include the device system log in your bug report (I realise that can be tricky when dealing with customer devices; one option is to ask the customer to install Apple Configurator, which lets them view the system log). And if you do file a bug, please post your bug number, just for the record.
On behalf of Apple I’d like to thank everyone for their efforts in helping to track down this rather horrid issue.
Share and Enjoy
This held me up for 2 hours before I found a quick "fix" - reboot the iOS device
A quote from the discussion at http://forums.developer.apple.com/thread/4743,
From user littledetails
As others have reported, this mysterious keychain error is most easily observable when launching via Xcode with the debugger attached. Once the error starts occurring, the keychain doesn't seem to right itself regardless of memory pressure until one reboots the device.
When I rebooted my device the error went away, allowing me to continue testing. Not sure what else to do. In my situation, moving to NSUserDefaults or some other storage solution was not a possibility.
One way to get around this issue with the keychain is to use dispatch_async to allow the app to launch. This works when the app is opened from the background. Also make sure you have the kSecAttrAccessibleAfterFirstUnlock accessibility setting on the keychain.
dispatch_async(dispatch_get_main_queue(), ^{
// save/write to keychain
})
I am using GenericKeychain classes from apple:
https://developer.apple.com/library/content/samplecode/GenericKeychain/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007797-Intro-DontLinkElementID_2
struct KeychainConfiguration {
static let serviceName = "MyAppService"
/*
Specifying an access group to use with `KeychainPasswordItem` instances will create items shared accross both apps.
For information on App ID prefixes, see:
https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/AppID.html
and:
https://developer.apple.com/library/ios/technotes/tn2311/_index.html
*/
// static let accessGroup = "[YOUR APP ID PREFIX].com.example.apple-samplecode.GenericKeychainShared"
/*
Not specifying an access group to use with `KeychainPasswordItem` instances
will create items specific to each app.
*/
static let accessGroup: String? = nil
}
In this file I was specifying my custom accessGroup in this line static let accessGroup = "[YOUR APP ID PREFIX].com.example.apple-samplecode.GenericKeychainShared"
After returning to static let accessGroup: String? = nil the problem was gone. :)
Make sure keychain sharing must on under Capabilities in project Target.
In my case the App_Name.entitlements file has different bundle id than of my project bundle id. So, I change bundle id in the App_Name.entitlements file as of my project bundle id.
e.g., Suppose your project bundle id is com.Apple.testApp then got to
App_Name.entitlements file open key Keychain Access Groups key which is of Array type.
Under item0 set value of your project bundle id as eg:- $(AppIdentifierPrefix)com.Apple.testAp.
According to #iCaramba's answer. I've found a workaround:
Stop the task to kill the app (if you are already running the app)
Launch the app on your device manually. DO NOT use Xcode
Use Xcode to re-launch the app

Adding keychain sharing to production app that already has users

We have an iOS app that has been released. The IDE is XCode6. I want to add keychain sharing to access the sessionID that exists in the app from an iOS 8 share extension.
Problem is whenever keychain sharing is turned on, the sessionID that already exists can no longer be accessed.
It can be accessed whenever keychain sharing is turned off.
This dictionary is passed into SecItemCopyMatching, which always returns -25300 (not found) whenever keychain sharing is enabled, no matter what the "Keychain Groups:" is.
[0] (null) #"svce" : #"SESSION_ID_KEY"
[1] (null) #"r_Data" : #"1"
[2] (null) #"m_Limit" : #"m_LimitOne"
[3] (null) #"class" : #"genp"
[4] (null) #"acct" : #"SESSION_ID_KEY"
[5] (null) #"pdmn" : #"ck"
Any idea why access to the key might not work? I tried setting kSecAttrAccessGroup with the bundle prefix and name and it still did not work on the simulator.
Hopefully I got your answer and the bounty :)
I had the same issue originally and came across this post, and I know you mentioned you tried with the bundle prefix and name. But let's run through a sanity check.
In the MyApp.entitlements and in MyApp Extension.entitlements I have the Keychain Access Groups set to $(AppIdentifierPrefix)com.company.MyApp (this is the default).
I accessed the value for ABCD1234 (aka AppIdentifierPrefix value) using this SO answer https://stackoverflow.com/a/20340883 however hardcoding may not be best practice here, so consider looking this a solution like this https://stackoverflow.com/a/11841898/2588957
Then note in my app all I added to make my current code to work is the following:
[keychainItem setObject:#"ABCD1234.com.company.MyApp" forKey:(__bridge id)kSecAttrAccessGroup]; before updating the item and I can now access the keychain item in my share extension.
I had a similar issue when implementing inter-app communication in iOS 7 a couple of months ago.
I found this remark on Apple's GenericKeyChain sample project:
// Apps that are built for the simulator aren't signed, so there's no keychain access group
// for the simulator to check. This means that all apps can see all keychain items when run
// on the simulator.
//
// If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
// simulator will return -25243 (errSecNoAccessForItem).
So if you're testing on a Simulator you need to remove the "kSecAttrAccessGroup".
On a device it should work with this key.

iOS Keychain SecItemAdd returns -25243

I'm working on updating an iPhone application with a minor change in its default configuration. It's been awhile since I've built it last, though, and so I've upgraded Xcode to 4.2 and included iOS 5 support in the latest builds.
When I go to test on the device, I get the following assertion error:
2011-11-02 20:57:18.869 RoseBandwidth[903:707] Tried to add item, got result: -25243
2011-11-02 20:57:18.870 RoseBandwidth[903:707] *** Assertion failure in -[KeychainItemWrapper writeToKeychain], /Users/tim/code/RoseBandwidth/Classes/KeychainItemWrapper.m:312
2011-11-02 20:57:18.872 RoseBandwidth[903:707] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Couldn't add the Keychain Item.'
I'm using the implementation of the KeychainItemWrapper class from Apple's GenericKeychain project. It's worth noting that this error only shows up on the device, not in the Simulator (and I'm aware of the access group restriction differences between platforms, but usually I thought that caused problems on the Simulator, not actual hardware).
Why would I be getting this error back? I've touched nothing relevant to the keychain-related parts of the app; it stores and retrieves data exactly like it used to.
Okay, I couldn't quite get your project to build, but from How to share keychain data between iOS applications I think you might want to check your entitlements file. At least in the github project you didn't have anything specified in the Keychain Access Groups.
For future searchers who happen to end up here, another possible cause of the -25243 error (which means No access control, BTW) is running on the simulator.
My best theory is the app's provisioning profile (or the signature thereof) is how the app knows what its bundle seed is. And the bundle seed needs to be part of the your keychain's access group name. But apps run on the simulator don't get signed, and so have a missing (or different?) bundle seed than you specified keychain-access-group.
Or something. It's all so poorly documented, it's hard to tell what's what. Just try running it on a device and see if that helps.
For those of you getting this error and trying to achieve "Shared Key Chain Access" between two apps:
You need to create an App Id for your app with same Team Id you selected when you first activated "Shared Keychain Access" in 'Capabilities'. Create your App Id in here:
Apple Member Center
After that you need to create provisioning profile from that App Id and download it to your computer.(Double click it to install to x-code)
I assume you already know you need "App ID Prefix" to access key chain, but for those who don't know:
"App ID Prefix" is unique text identifier associated with your Apple developer account:
To access "SharedKeychain" you need to implement it like this before you try to write or read from keychain
keychainAccessGroupName = "AB123CDE45.myKeyChainGroup":
You can check out this tutorial for further info:Share Keychain between iOS apps.
Hope that helps.
I get the same error from time to time in the simulator even if I did not touch the code. A reset of the simulator solves the problem for me.
See this question/answer how to reset the simulator: https://stackoverflow.com/a/3442326
As others have pointed out, in device builds error -25243 is often caused by trying to access a keychain access group that you don't have permissions for. (It's missing from your Entitlements.plist file or your provisioning profile.)
But in the simulator there can be another cause. The simulator doesn't support keychain access groups at all, so if you set the kSecAttrAccessGroup property on a keychain item and try to write it you'll get this -25243 error code.
FYI, Apple's GenericKeychain sample code has this comment:
// Ignore the access group if running on the iPhone simulator.
//
// Apps that are built for the simulator aren't signed, so there's no keychain access group
// for the simulator to check. This means that all apps can see all keychain items when run
// on the simulator.
//
// If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
// simulator will return -25243 (errSecNoAccessForItem).
This worked for me when I used a production certificate and provisioning profile. Using debug did not work.
In my experience, I get that return value -25243 when I realized that I was trying to pass kSecMatchLimit with kSecMatchLimitOne and kSecReturnData with kCFBooleanTrue values to the SecItemAdd() function. I removed those and double checked the app ids and provisioning profiles and everything is good.
I am not sure if this is helpful or not, but in my experience if you will use SecItemAdd() function for shared keychain access, those two parameters must not be there.

Resources