Swift钥匙串-存储OAuth凭据:“钥匙串中已存在指定的项目”

问题描述 投票:1回答:1

我正在为我的网站构建一个iOS应用,并且正在尝试使用OAuth2来管理登录凭据。在用户登录时,我使用提供的用户名和密码成功命中了身份验证端点,并且尝试将访问令牌和刷新令牌存储在钥匙串中,因此用户不必继续提供凭据。

根据这些来源的指示,我在将刷新令牌和访问令牌存储到我的钥匙串时遇到了麻烦:

我能够成功存储访问令牌或刷新令牌,但是无论我先存储哪个令牌,当尝试存储另一个令牌时,我都会收到以下错误消息:“指定的项已存在于钥匙串中。“

我添加了CheckForExisting函数以删除具有相同规格的任何现有项,但是当我尝试使用相同的query删除现有的钥匙串项时,我会收到errSecItemNotFound状态。因此,很令人沮丧的是,我被告知无法创建我的商品,因为它已经存在,但是我无法删除现有商品,因为不存在任何现有商品。

我的假设是,访问令牌项目的创建会阻止刷新令牌项目的创建,因此我希望有人可以对以下内容有所了解:

  1. 为什么第二项创建被阻止?钥匙串是否有一些我要打的内置主键检查(例如不能存储多个kSecClassInternetPassword)?
  2. 区分两个标记的正确方法是什么?现在我正在使用kSecAttrLabel,但这是黑暗中的镜头。

请注意,我希望得到有关[[为什么的解释,但我目前的方法失败了。我绝对欢迎替代实现,但是我真的很想了解这里幕后发生的事情,因此,如果可能的话,请提供一个解释,说明替代实现在何处避免了我似乎已经沦为陷阱的陷阱。

存储令牌的Swift4代码:

func StoreTokens(username: String, access_token: String, refresh_token: String) throws { func CheckForExisting(query: [String: Any]) throws { let status = SecItemDelete(query as CFDictionary) guard status == errSecSuccess || status == errSecItemNotFound else { let error_message = SecCopyErrorMessageString(status, nil)! throw KeychainError.unhandledError(status: error_message) } } let configuration = ConfigurationDetails() let server = configuration.server let access_token = access_token.data(using: String.Encoding.utf8)! let refresh_token = refresh_token.data(using: String.Encoding.utf8)! let access_token_query: [String: Any] = [ kSecClass as String: kSecClassInternetPassword, kSecAttrAccount as String: username, kSecAttrServer as String: server, kSecAttrLabel as String: "AccessToken", kSecValueData as String: access_token ] let refresh_token_query: [String: Any] = [ kSecClass as String: kSecClassInternetPassword, kSecAttrAccount as String: username, kSecAttrServer as String: server, kSecAttrLabel as String: "RefreshToken", kSecValueData as String: refresh_token ] try CheckForExisting(query: access_token_query) let access_status = SecItemAdd(access_token_query as CFDictionary, nil) guard access_status == errSecSuccess else { let error_message = SecCopyErrorMessageString(access_status, nil)! throw KeychainError.unhandledError(status: error_message) } try CheckForExisting(query: refresh_token_query) let refresh_status = SecItemAdd(refresh_token_query as CFDictionary, nil) guard refresh_status == errSecSuccess else { let error_message = SecCopyErrorMessageString(refresh_status, nil)! throw KeychainError.unhandledError(status: error_message) } }

oauth-2.0 swift4 keychain
1个回答
0
投票
据此https://developer.apple.com/documentation/security/errsecduplicateitem看起来像类kSecClassInternetPassword的唯一键仅包含以下属性:kSecAttrAccount,kSecAttrSecurityDomain,kSecAttrServer,kSecAttrProtocol,kSecAttrAuthenticationType,kSecAttrPort和kSecAttrPath。

因此,kSecAttrLabel不在列表中,并且您的refresh_token_query复制了access_token_query。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.