Rodrigo Rodrigo - 2 months ago 20
Swift Question

Retrieving keychain value with A0SimpleKeychain returning nil in OS10

I'm new to swift so bear with me. I'm trying to store a user's token using Auth0's library A0SimpleKeychain: https://github.com/auth0/SimpleKeychain. I followed their docs and I came up with this login function:

@IBAction func login(_ sender: UIButton) {
let payload: Parameters = [
"username": self.usernameTextField.text!,
"password": self.passwordTextField.text!
]

Alamofire.request("my/url", method: .post, parameters: payload, encoding: JSONEncoding.default).responseJSON { response in

let json = JSON(response.result.value)
let token = json["token"]

let jwtToken = token.string!

A0SimpleKeychain().setString(jwtToken, forKey:"user-jwt")

let jwt = A0SimpleKeychain().string(forKey: "user-jwt")

print(jwt)
}
}


The issue I'm having it that
print(jwt)
which should print the token prints
nil
instead. If I print out
jwtToken
then it prints out the correct value so I know it's not nil. I've tried just putting a "test" string to see if there was any issues with my
jwtToken
since I'm still understanding optionals and unwrapping them but it also just returned nil.

A0SimpleKeychain().setString("testString", forKey:"user-jwt")


I'm running on OSX 10.11.6 and Swift 3

Answer

Nothing's wrong with the code. This is a project settings issue. KeyChains do not exist in a vacuum; to be secure they are only allowed to operate by the entitlements specified by your code-signed App, and these entitlements are sealed at build time due to the code signing. It appears that a bug in Xcode / iOS 10, at least in the simulator, is not respecting or not setting the default keychain entitlement application-identifier and to activate it you must also enable the keychain-access-groups entitlement.

[EDIT] If you change your Build target to 8.4 and simulate an 8.4 device, you will see it works without modifying settings.

To work under iOS 10, under your target's project settings, go to the second tab Capabilities and enable "Keychain Sharing". You will be prompted for your Apple ID password and asked which Apple ID to attach the keychain to.

The error code you were getting deep down was -34018. You really need to check the return value of setString, which can be false.

(EDIT) Reference: A0SimpleKeyChain.m:151 OSStatus status = SecItemAdd((__bridge CFDictionaryRef)newQuery, NULL); -> -34018

SecItemAdd and SecItemCopyMatching returns error code -34018 (errSecMissingEntitlement)

https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/02concepts/concepts.html

"From a high level perspective, Keychain Services uses an app’s code signature with its embedded entitlements to ensure that only an authorized app can access a particular keychain item."