AWS Cognito Swift:首次登录后Token无法更新的问题求助
解决AWS Cognito二次登录后Token未更新的问题
问题现象
- 首次登录时,
Login with Token与Current Token输出一致 - 二次及后续登录时,传入的新Token能在
loginCognito中正常打印,但getLoginsToken返回的始终是首次登录的旧Token - 尝试调用
credentialsProvider.clearCredentials()无法解决问题
核心原因
- 原代码中
IdentityProviderManager的loginMaps是初始化时固定的,没有动态更新机制,一旦创建就只能返回初始Token AWSCognitoCredentialsProvider默认会缓存身份提供者实例和身份ID,二次登录时即使创建新的credentialsProvider,旧的缓存实例依然会被复用,导致返回旧Token
解决方案
1. 修改IdentityProviderManager支持动态更新Token
让身份提供者类可以随时更新存储的Token,不用每次登录都创建新实例:
private class IdentityProviderManager: NSObject, AWSIdentityProviderManager { private var loginMaps: [String: String] init(loginMaps: [String: String]) { self.loginMaps = loginMaps super.init() } // 新增方法:动态更新指定key的Token func updateLoginToken(for key: String, token: String) { loginMaps[key] = token } func logins() -> AWSTask<NSDictionary> { return AWSTask(result: loginMaps as NSDictionary) } }
2. 重构loginCognito函数,复用实例+清空缓存
优先复用已有的凭证提供者实例,更新Token后强制清空缓存并刷新,确保Cognito使用最新Token:
private func loginCognito(data: AWSConfigData) async throws { let loginsKey = "cognito-idp.\(data.region).amazonaws.com/\(data.userPoolId)" var credentialsProvider: AWSCognitoCredentialsProvider // 检查是否已有可用的凭证提供者实例 if let existingConfig = AWSServiceManager.default()?.defaultServiceConfiguration, let existingProvider = existingConfig.credentialsProvider as? AWSCognitoCredentialsProvider, let identityManager = existingProvider.identityProvider as? IdentityProviderManager { // 更新现有实例的Token identityManager.updateLoginToken(for: loginsKey, token: data.idToken) credentialsProvider = existingProvider // 清空缓存的凭证和身份ID,强制Cognito刷新 credentialsProvider.clearCredentials() credentialsProvider.clearIdentityId() } else { // 首次登录:创建新的实例 let logins = [loginsKey: data.idToken] let identityProviderManager = IdentityProviderManager(loginMaps: logins) credentialsProvider = AWSCognitoCredentialsProvider( regionType: data.regionType, identityPoolId: data.identityPoolId, identityProviderManager: identityProviderManager ) } self.awsConfigData = data let configuration = AWSServiceConfiguration( region: data.regionType, credentialsProvider: credentialsProvider ) AWSServiceManager.default()?.defaultServiceConfiguration = configuration // 等待凭证刷新完成,确保新Token生效 return try await withCheckedThrowingContinuation { continuation in credentialsProvider.refresh().continueWith { task in if let error = task.error { continuation.resume(throwing: error) } else { // 打印更新后的Token credentialsProvider.identityProvider.logins().continueWith { loginTask in if let result = loginTask.result, let token = result[loginsKey] as? String { print("Login with Token:", token) } continuation.resume(returning: ()) } } } } // 验证最新Token Task { let currentToken = try await self.getLoginsToken() print("Current Token:", currentToken) } }
3. getLoginsToken函数无需修改
原函数逻辑可以保持不变,现在它会从更新后的身份提供者实例中获取最新Token:
private func getLoginsToken() async throws -> String { guard let configuration = AWSServiceManager.default().defaultServiceConfiguration, let credentialsProvider = configuration.credentialsProvider as? AWSCognitoCredentialsProvider, let awsConfigData else { let error = NSError(domain: "S3Error", code: -1, userInfo: [NSLocalizedDescriptionKey: "Cannot get credentialsProvider"]) print("Token Error:", error) throw error } return try await withCheckedThrowingContinuation { continuation in credentialsProvider.identityProvider.logins().continueWith { task in let loginsKey = "cognito-idp.\(awsConfigData.region).amazonaws.com/\(awsConfigData.userPoolId)" if let result = task.result, let token = result[loginsKey] as? String { print("Token:", token) return continuation.resume(returning: token) } else if let error = task.error { print("Token Error:", error) return continuation.resume(throwing: error) } else { let error = NSError(domain: "S3Error", code: -1, userInfo: [NSLocalizedDescriptionKey: "Get login error"]) return continuation.resume(throwing: error) } } } }
关键修改说明
- 让
IdentityProviderManager支持动态更新Token,避免重复创建实例 - 登录时复用现有凭证提供者,同时调用
clearCredentials()和clearIdentityId()彻底清空缓存 - 调用
credentialsProvider.refresh()强制Cognito服务刷新凭证,确保新Token立即生效
内容的提问来源于stack exchange,提问作者Nguyễn Đức Thành
相关产品推荐
相关产品推荐

