Swift封装AWS Amplify全局fetchSession获取idToken报错问题
全局获取AWS Cognito有效idToken实现方案
报错原因
- 第一次报
Unexpected non-void return value in void function:Amplify.Auth.fetchAuthSession是异步方法,其入参的completion闭包返回值类型为Void,在闭包内部写return返回值无法被外部函数接收,不符合闭包定义所以报错。 - 第二次报类型不匹配:手动给completion闭包声明了
-> AnyObject返回值,和Amplify SDK定义的闭包类型(Result<AuthSession, AuthError>) -> Void冲突,编译器无法识别该参数类型。
实现逻辑说明
AWS Cognito的idToken默认有效期为5分钟,Amplify SDK内部已经内置了自动刷新逻辑,只要用户登录态有效,调用接口时会自动判断token是否临近过期,自动通过refreshToken换取新的有效token,不需要开发者自行编写定时刷新逻辑。只需要封装全局可访问的异步方法,每次需要token时直接调用获取最新有效值即可,不要自行本地缓存token避免拿到过期值。
完整实现代码
推荐使用Swift 5.5+的async/await语法封装,代码更简洁易读,全局通过单例调用:
import Amplify import AWSCognitoAuthPlugin class AuthManager { // 全局单例,应用内任意位置可直接访问 static let shared = AuthManager() private init() {} /// 获取最新有效Cognito idToken /// - Throws: 登录态失效、网络错误等异常 /// - Returns: 有效的idToken字符串 func fetchIdToken() async throws -> String { let session = try await Amplify.Auth.fetchAuthSession() guard let cognitoTokenProvider = session as? AuthCognitoTokensProvider else { throw NSError( domain: "AuthServiceError", code: -1, userInfo: [NSLocalizedDescriptionKey: "当前登录状态异常,无法获取用户令牌"] ) } let tokens = try cognitoTokenProvider.getCognitoTokens().get() return tokens.idToken } }
如果需要兼容iOS 15以下的系统版本,可以使用completion回调的封装方式:
func fetchIdToken(completion: @escaping (Result<String, Error>) -> Void) { Amplify.Auth.fetchAuthSession { result in switch result { case .success(let session): guard let cognitoTokenProvider = session as? AuthCognitoTokensProvider else { completion(.failure(NSError( domain: "AuthServiceError", code: -1, userInfo: [NSLocalizedDescriptionKey: "当前登录状态异常,无法获取用户令牌"] ))) return } do { let tokens = try cognitoTokenProvider.getCognitoTokens().get() completion(.success(tokens.idToken)) } catch { completion(.failure(error)) } case .failure(let error): completion(.failure(error)) } } }
调用示例
async/await 调用(推荐)
在任意需要获取token的位置(比如网络请求拦截器、接口调用前)通过Task包裹调用:
// 示例:给网络请求添加Authorization头 Task { do { let validToken = try await AuthManager.shared.fetchIdToken() var request = URLRequest(url: URL(string: "你的接口地址")!) request.setValue("Bearer \(validToken)", forHTTPHeaderField: "Authorization") // 执行后续网络请求逻辑 } catch { print("获取token失败:\(error.localizedDescription)") // 可在此处处理登录态失效逻辑,比如跳转至登录页 } }
回调方式调用
AuthManager.shared.fetchIdToken { [weak self] result in switch result { case .success(let idToken): // 拿到有效token执行业务逻辑 print("获取token成功:\(idToken)") case .failure(let error): // 处理错误 print("获取token失败:\(error.localizedDescription)") } }
内容的提问来源于stack exchange,提问作者SadDeveloper
相关产品推荐
相关产品推荐

