You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native集成ForgeRock及处理RefreshToken时重启获取AccessToken失败

问题:应用重启/杀死后无法获取ForgeRock AccessToken

按照ForgeRock官方React Native集成文档完成集成后,应用运行正常,但应用被杀死或重载后,调用原生方法获取AccessToken时触发错误:"Invalid SDK state: No current user for which to request access tokens"。根据文档提示,原生SDK未初始化可能导致该错误,相关代码及错误信息如下:


调用的getAccessToken方法

@objc func getAccessToken(
    _ resolve: @escaping RCTPromiseResolveBlock,
    rejecter reject: @escaping RCTPromiseRejectBlock) {
      
      guard let user = FRUser.currentUser else {
        /**
         * If no currently authenticated user is found, log error.
         */
        let errorMsg = "Invalid SDK state: No current user for which to request access tokens"
        FRLog.e(errorMsg)
        reject("error", errorMsg, nil)
        return
      }
      user.getAccessToken { user, error in
        if let error = error {
          FRLog.e(String(describing: error))
          reject("error", error.localizedDescription, error)
        }
        else if let user = user, let accessToken = user.token {
          let encoder = JSONEncoder()
          
          do {
            let data = try encoder.encode(accessToken)
            let string = String(data: data, encoding: .utf8)
            FRLog.i(string ?? "Encoding of token failed")
            resolve(string)
          } catch {
            reject("Error", "Serialization of tokens failed", error)
          }
        }
        else {
          let errorMsg = "Invalid SDK state: getAccessToken returned no result"
          FRLog.e(errorMsg)
          reject("error", errorMsg, nil)
        }
      }
    }

FRUser的getAccessToken实现

//  MARK: - AccessToken
    
    /// Retrieves access_token from Keychain storage, and if current access_token is expired, then consumes refresh_token to refresh access_token, and returns FRUser with newly granted access_token
    ///
    /// - Parameter completion: Completion block which returns newly refreshed FRUser object
    @objc
    public func getAccessToken(completion:@escaping UserCallback) {
        if let frAuth = FRAuth.shared, let tokenManager = frAuth.tokenManager {
            tokenManager.getAccessToken { (token, error) in
                if let token = token {
                    self.token = token
                    self.save()
                    completion(self, nil)
                }
                else {
                    completion(nil, error)
                }
            }
        }
        else {
            FRLog.w("Invalid SDK state; missing TokenManager")
            completion(nil, ConfigError.invalidSDKState)
        }
    }

FRUser的currentUser代码

/**
     Singleton instance represents currently authenticated user.
     
     ## Note ##
     If SDK has not been started using *FRAuth.start()*, *FRUser.currentUser* returns nil even if user session has previously authenticated, and valid.
     *FRUser.currentUser* would only returns an object when there is either or both of following:
        - Session Token authenticated by AM's Authentication Tree
        - OAuth2 token set issued by previously authenticated Session Token
     */
    @objc
    public static var currentUser: FRUser? {
        get {
            if let staticUser = _staticUser {
                return staticUser
            }
            else if let frAuth = FRAuth.shared {
                
                FRLog.v("FRUser retrieved from SessionManager")
                if let accessToken = try? frAuth.keychainManager.getAccessToken() {
                    _staticUser = FRUser(token: accessToken)
                }
                else if let _ = frAuth.keychainManager.getSSOToken() {
                    _staticUser = FRUser(token: nil)
                }
                
                return _staticUser
            }
            
            FRLog.w("Invalid SDK State: FRUser is returning 'nil'.")
            return nil
        }
    }

触发的错误信息

Invalid SDK state: No current user for which to request access tokens

排查与解决步骤

1. 确保应用启动时优先初始化ForgeRock SDK

从FRUser.currentUser的注释明确可知:必须先调用FRAuth.start()初始化SDK,否则即使钥匙串中有有效会话,currentUser也会返回nil。需在应用启动的最早期执行初始化,比如在AppDelegate的didFinishLaunchingWithOptions中:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // 优先初始化ForgeRock SDK
    do {
        try FRAuth.start()
    } catch {
        FRLog.e("Failed to start ForgeRock SDK: \(error)")
    }
    // 其他React Native初始化逻辑
    return true
}

2. 检查钥匙串配置与访问权限

ForgeRock SDK依赖钥匙串存储会话和令牌,需确认:

  • Entitlements.plist中已开启钥匙串访问权限
  • SDK初始化配置包含正确的钥匙串组(若使用App Groups)
  • 用户认证后,accessToken或SSOToken确实被写入钥匙串(可在认证后直接调用frAuth.keychainManager.getAccessToken()验证)

3. 避免过早调用令牌获取方法

确保SDK初始化完成后,再调用getAccessToken。若由React Native侧触发调用,可在原生模块中添加初始化完成回调,或延迟执行令牌获取逻辑。

4. 验证令牌持久化逻辑

检查FRUser的save()方法是否正确将令牌写入钥匙串:

  • 确认save()调用了keychainManager.setAccessToken()或相关持久化API
  • 验证令牌过期后,刷新逻辑能正确更新钥匙串中的令牌

5. 调试钥匙串读取流程

在FRUser.currentUser的getter中添加日志,确认:

  • FRAuth.shared不为nil(SDK已初始化)
  • keychainManager.getAccessToken()/getSSOToken()能读取到值
    若读取失败,说明令牌未被正确持久化或钥匙串访问异常

内容的提问来源于stack exchange,提问作者Jalson1982

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 17:44:54