Apple Watch 配套应用中访问令牌与刷新令牌的处理
解决Apple Watch刷新令牌不影响iPhone应用令牌的问题
问题根源
你的问题核心在于OAuth2协议的刷新令牌机制:大多数认证服务在刷新令牌时,会废弃旧的刷新令牌并返回新令牌。当iPhone和Watch共用同一个刷新令牌时,Watch端调用刷新接口后,服务器会失效旧令牌,导致iPhone端存储的刷新令牌无法再使用,进而触发登出。
解决方案
1. 为Watch分配独立的刷新令牌
这是最彻底的解决方案,需要服务器端配合支持多设备令牌管理:
- iPhone登录成功后,除了自身的访问/刷新令牌,发起一个"Watch设备绑定"请求,服务器为该Watch生成独立的刷新令牌(与iPhone的刷新令牌相互独立);
- 通过WatchConnectivity将初始访问令牌+绑定凭证(如临时授权码)发送给Watch,Watch使用绑定凭证向服务器请求专属的刷新令牌,并存入本地钥匙串;
- 后续Watch刷新令牌时,仅使用自己的独立刷新令牌,不会影响iPhone端的令牌有效性。
2. 优化跨设备令牌同步逻辑
如果暂时无法修改服务器端,可通过调整客户端同步策略避免互相影响:
- 两端仅同步访问令牌,不同步刷新令牌;
- iPhone端刷新令牌后,将新的访问令牌通过WatchConnectivity同步给Watch,覆盖Watch的访问令牌,但保留Watch的刷新令牌;
- Watch端刷新令牌后,同样仅同步新的访问令牌给iPhone,不修改iPhone的刷新令牌;
- 这种方式下,两端各自用自己的刷新令牌刷新,仅共享最新的访问令牌,避免互相踢下线。
3. 服务器端调整令牌策略(可选)
如果服务器可控,可做以下优化:
- 启用刷新令牌滚动有效期:刷新时返回新的刷新令牌,同时保留旧的刷新令牌一段时间(如5-10分钟),给两端足够的同步窗口;
- 支持多设备刷新令牌关联:将同一个用户的多个设备刷新令牌关联到用户ID下,刷新某一个设备的令牌时,仅失效该设备的旧令牌,不影响其他设备。
代码示例(Swift)
Watch端刷新令牌并同步访问令牌
func refreshWatchTokens() { guard let refreshToken = KeychainService.load(key: "watch_refresh_token") else { return } // 调用服务器刷新接口,获取新的访问令牌和Watch专属的刷新令牌 AuthAPI.refreshToken(refreshToken: refreshToken) { [weak self] result in guard let self = self else { return } switch result { case .success(let newTokens): // 保存Watch自己的令牌 KeychainService.save(key: "watch_access_token", value: newTokens.accessToken) KeychainService.save(key: "watch_refresh_token", value: newTokens.refreshToken) // 仅同步访问令牌到iPhone if WCSession.default.isReachable { do { try WCSession.default.updateApplicationContext([ "shared_access_token": newTokens.accessToken ]) } catch { print("Sync access token to iPhone failed: \(error.localizedDescription)") } } case .failure(let error): print("Refresh watch tokens failed: \(error.localizedDescription)") } } }
iPhone端接收同步的访问令牌
// 实现WCSessionDelegate方法 func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) { if let newAccessToken = applicationContext["shared_access_token"] as? String { // 更新iPhone的访问令牌,保留原有刷新令牌 KeychainService.save(key: "iphone_access_token", value: newAccessToken) } }
内容的提问来源于stack exchange,提问作者Simone
相关产品推荐
相关产品推荐

