繁体   English   中英

Firebase iOS 上的 AppCheck:403 权限错误 - PERMISSION_DENIED

[英]Firebase AppCheck on iOS: 403 permission errors - PERMISSION_DENIED

Q:Firebase App Check权限错误如何解决?

背景:我已经根据文档启用了 App Check:

DeviceCheck 已启用/配置: https://firebase.google.com/docs/app-check/ios/devicecheck-provider

App Attest 已启用,配置如下: https://firebase.google.com/docs/app-check/ios/devicecheck-provider

SDK 添加到项目中,代码来自: https://github.com/firebase/firebase-ios-sdk/blob/master/FirebaseAppCheck/Apps/FIRAppCheckTestApp/FIRAppCheckTestApp/AppDelegate.swift

具体来说,在 appdelegate: Token 设置中:

FirebaseApp.configure()

requestDeviceCheckToken()

requestDebugToken()

if #available(iOS 14.0, *) {
  requestAppAttestToken()
}

打电话:

  // MARK: App Check providers
  func requestDeviceCheckToken() {
    guard let firebaseApp = FirebaseApp.app() else {
      return
    }

    DeviceCheckProvider(app: firebaseApp)?.getToken { token, error in
      if let token = token {
        print("DeviceCheck token: \(token.token), expiration date: \(token.expirationDate)")
      }

      if let error = error {
        print("DeviceCheck error: \((error as NSError).userInfo)")
      }
    }
  }

  func requestDebugToken() {
    guard let firebaseApp = FirebaseApp.app() else {
      return
    }

    if let debugProvider = AppCheckDebugProvider(app: firebaseApp) {
      print("Debug token: \(debugProvider.currentDebugToken())")

      debugProvider.getToken { token, error in
        if let token = token {
          print("Debug FAC token: \(token.token), expiration date: \(token.expirationDate)")
        }

        if let error = error {
          print("Debug error: \(error)")
        }
      }
    }
  }

  @available(iOS 14.0, *)
  func requestAppAttestToken() {
    guard let firebaseApp = FirebaseApp.app() else {
      return
    }

    guard let appAttestProvider = AppAttestProvider(app: firebaseApp) else {
      print("Failed to instantiate AppAttestProvider")
      return
    }

    appAttestProvider.getToken { token, error in
      if let token = token {
        print("App Attest FAC token: \(token.token), expiration date: \(token.expirationDate)")
      }

      if let error = error {
        print("App Attest error: \(error)")
      }
    }
  }

requestDeviceCheckToken() 返回权限错误:

DeviceCheck error: ["NSLocalizedFailureReason": The server responded with an error: 
 - URL: https://firebaseappcheck.googleapis.com/v1beta/projects/<GOOGLE_APP_ID>:exchangeDeviceCheckToken 
 - HTTP status code: 403 
 - Response body: {
  "error": {
    "code": 403,
    "message": "Requests from this iOS client application \u003cempty\u003e are blocked.",
    "status": "PERMISSION_DENIED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "API_KEY_IOS_APP_BLOCKED",
        "domain": "googleapis.com",
        "metadata": {
          "service": "firebaseappcheck.googleapis.com",
          "consumer": "projects/<my project #>"
        }
      }
    ]
  }
}

requestDebugToken() 返回权限错误:

Debug error: Error Domain=com.firebase.appCheck Code=0 "The server responded with an error: 
 - URL: https://firebaseappcheck.googleapis.com/v1beta/projects/<GOOGLE_APP_ID>:exchangeDebugToken 
 - HTTP status code: 403 
 - Response body: {
  "error": {
    "code": 403,
    "message": "Requests from this iOS client application \u003cempty\u003e are blocked.",
    "status": "PERMISSION_DENIED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "API_KEY_IOS_APP_BLOCKED",
        "domain": "googleapis.com",
        "metadata": {
          "consumer": "projects/<my project #>",
          "service": "firebaseappcheck.googleapis.com"
        }
      }
    ]
  }
}
" UserInfo={NSLocalizedFailureReason=The server responded with an error: 
 - URL: https://firebaseappcheck.googleapis.com/v1beta/projects/<GOOGLE_APP_ID>:exchangeDebugToken 
 - HTTP status code: 403 
 - Response body: {
  "error": {
    "code": 403,
    "message": "Requests from this iOS client application \u003cempty\u003e are blocked.",
    "status": "PERMISSION_DENIED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "API_KEY_IOS_APP_BLOCKED",
        "domain": "googleapis.com",
        "metadata": {
          "consumer": "projects/<my project #",
          "service": "firebaseappcheck.googleapis.com"
        }
      }
    ]
  }
}
}

requestAppAttestToken() 返回错误:

App Attest error: Error Domain=com.firebase.appCheck Code=0 "(null)"

GCP Console 确实显示了对以下 w/100% 错误的所有调用:

google.firebase.appcheck.v1beta.TokenExchangeService.ExchangeDebugToken 
    google.firebase.appcheck.v1beta.TokenExchangeService.ExchangeDeviceCheckToken   
    google.firebase.appcheck.v1beta.TokenExchangeService.GenerateAppAttestChallenge 

所有这些似乎都指向权限错误? 具体来说,GOOGLE_APP_ID在request URL中,但是通过控制台在Firebase中配置了App Check...

我没有在文档中看到任何内容,或者在 IAM 中没有看到我错过的任何明显内容? :(

提前寻求帮助!

更新后进一步测试 w/ Postman:

问题似乎是 SDK 在调用 AppCheck API 时没有正确传递X-Ios-Bundle-Identifier

得出这个结论的步骤:

  • 来自 POSTMAN:API 调用 w/ original API_KEY -> yields initial (above) error response/403
  • 从 POSTMAN: API 调用如上,+ X-Ios-Bundle-Identifier + valid debug_token -> 产生成功负载。

所以:

  • 有什么想法可以帮助识别为什么X-Ios-Bundle-Identifier没有被 SDK 传递? 该应用程序正在使用其他 Firebase API 的 w/out 问题,因此似乎仅限于 AppCheck SDK...
  • 和/或 - X-Ios-Bundle-Identifier能否以编程方式(在 Swift 中)添加到 AppCheck 调用中(它在 .plist 中被正确标记)

解决!

App Check SDK 目前不支持 Android / iOS API 键的应用限制。 因此,您必须删除 API 密钥的应用程序限制才能解决此问题。

希望应用程序限制会在某个时候得到支持......

更新!

v8.8.0-beta 现在支持 bundle ID: :)

1.配置DeviceCheck私钥

  • 确保您已经为 DeviceCheck 创建了私钥在此处输入图像描述

  • 并将其安装在 AppCheck 选项卡下的 firebase 项目设置中在此处输入图像描述

https://firebase.google.com/docs/app-check/ios/devicecheck-provider

2. 将调试令牌添加到 firebase。

如果你使用 AppCheckDebugProvider(主要用于模拟器),运行项目后你会在控制台看到一个调试令牌,你需要将其复制并添加到项目设置的 AppCheck 中。 AppCheck 将批准它。 也不要忘记为 Arguments 添加-FIRDebugEnabled Arguments Passed on Launch

https://firebase.google.com/docs/app-check/ios/debug-provider

3. 为 AppAttest 环境添加生产授权。

AppCheck 的 beta 版本不适用于 AppAttest 开发环境,因此您需要在您的权利中设置production环境。 默认情况下,AppAttest 在开发环境中工作,无论您在市场上做出何种选择,它都可以在生产环境中工作。

https://firebase.google.com/docs/app-check/ios/app-attest-provider

https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_devicecheck_appattest-environment

在此处输入图像描述

4.可选:

你可以简化代码

#if targetEnvironment (simulator)
    let providerFactory = AppCheckDebugProviderFactory ()
#else
    let providerFactory = CustomAppCheckProviderFactory ()
#endif

AppCheck.setAppCheckProviderFactory (providerFactory)

并获得令牌

if let fbApp = FirebaseApp.app () {
    providerFactory.createProvider(with: fbApp)?.getToken { token, error in
        if let token = token {
            print ("AppCheck token: \ (token.token), expiration date: \ (token.expirationDate)")
        } else if let error = error {
            print ("AppCheck error: \ (error as NSError).userInfo)")
        }
    }
}

或者如果你想保护非 firebase 资源,你可以获得这样的令牌:

AppCheck.appCheck().token (forcingRefresh: false) { token, error in
    if let token = token {
        print ("AppCheck token: \ (token.token), expiration date: \ (token.expirationDate)")
    } else if let error = error {
        print ("AppCheck error: \ (error as NSError).userInfo)")
    }
}

https://firebase.google.com/docs/app-check/ios/custom-resource

App Check SDK 目前不支持 Android / iOS API 键的应用限制。 因此,您必须删除 API 密钥的应用程序限制才能解决此问题。

希望应用程序限制会在某个时候得到支持......

收到此错误 - 这对我有用:

  • 在真正的 Android 设备上运行应用程序
  • 打开 Android Studio → Logcat → 搜索“DebugAppCheckProvider” → 复制调试密码
  • 在 Firebase Go 到“App Check”→ Apps → 3 dot menu → Manage debug token → Add token → name it → paste the debug secret
  • 在激活应用程序检查后添加令牌的控制台日志。
  try {
      await firebase.appCheck().activate("ignored", true);
      const token = await getAppCheckToken();
      console.log({ token });
   } catch (err) {      
      console.error(err);
   }
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM