0
votes

Communicating with a REST API and saving API token in iOS's keychain. But the keychain code is throwing a nil error.

KeychainAccess.swift:

public class func passwordForAccount(account: String, service: String = "keyChainDefaultService") -> String? {
    let queryAttributes = NSDictionary(objects: [secClassGenericPassword(), service, account, true], forKeys: [secClass(), secAttrService(), secAttrAccount(), secReturnData()])

    var retrievedData: NSData?
    var extractedData: AnyObject?
    let status = SecItemCopyMatching(queryAttributes, &extractedData)

    if (status == errSecSuccess) {
        retrievedData = extractedData as? NSData
    }
    let password = NSString(data: retrievedData!, encoding: NSUTF8StringEncoding)

    return (password as! String)
}

In the above code, retrievedData is nil. If I do print(status), I get -25300. This function is being called from a view controller:

// check if API token has expired
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let userTokenExpiryDate : String? = KeychainAccess.passwordForAccount("Auth_Token_Expiry", service: "KeyChainService")
let dateFromString : NSDate? = dateFormatter.dateFromString(userTokenExpiryDate!)
let now = NSDate()

I am not sure where I'm going wrong here. Any pointers?

1
Well, did you actually save the password before trying to read it? - Sulthan
Yes, the info it's trying to read is saved/updated when a user signs in. I was able to sign in fine (meaning the tokens were saved), but as soon as I hit the new viewcontroller (after signing in), it throws the nil error. - DemCodeLines
"able to sign in" and "tokens were saved" are two very different things. From the error you have given it seems nothing was saved. Maybe account or service are different when serving? E.g. different lowercase/uppercase letters? - Sulthan
pastebin.com/mDr44kUW <-- that is the code that runs when signing in. I would hope that it's running successfully and the tokens are being saved in the keychain. But if this isn't being saved, then I see why there is a problem. - DemCodeLines

1 Answers

0
votes
    var extractedData : AnyObject?;
    let status = withUnsafeMutablePointer(&extractedData) {
        SecItemCopyMatching(queryAttributes, UnsafeMutablePointer($0))
    }

Try doing it like this, this is how I had to get it working