有没有办法从 firebase 应用程序分发中以编程方式下载应用程序?

Is there any way to download apps programatically from firebase app distribution?

我的主要目标是以编程方式下载一个应用程序,该应用程序正在从 firebase 应用程序分发中分发给测试人员。效果应该和按下一样 从此处的应用分发指定版本的“下载”按钮:

我试过使用 Firebase REST API,但似乎只有用于列出指定应用的版本和上传版本的端点,没有下载选项。

我还检查了支持 firebase 存储的 firebase,但是您可以在没有存储的情况下添加应用程序版本,所以我假设它不是存储它们的地方。

“下载”按钮生成的下载 URL 遵循模式 https://firebaseappdistribution.googleapis.com/app-binary-downloads/firebase-app-distro/app-binaries/[PROJECT_ID]/[APP_ID]/e4faf167-0e3d-4b1a-82dd-44811c0b5e43.apk?token=[TOKEN][APP_ID] 之后的部分标识了该应用程序,但我无法找到它的来源。

甚至可以以这种方式下载应用程序吗?还有其他下载应用程序的方法吗?

经过几天的努力,我终于找到了解决办法!这绝对不是很好,并且使用的是 Firebase 内部 API,这在外部并不真正可用。我的解决方案使用两个 sessions.

第一个是来自 google.auth.transport.requests.AuthorizedSession 的授权 session,凭据如文章中所述生成:https://developers.google.com/docs/api/quickstart/python and then passed to AuthorizedSession. This session is working with documented firebase REST API,例如获取应用程序的所有已发布版本。

第二个用于内部 Firebase API 并需要浏览器 session 的 cookie。为了获取 cookie,我必须登录到 firebase 并导航到应用程序分发以下载该应用程序。我打开开发控制台 (F12) 并观察到“网络”选项卡。 Firebase 正在发出 2 个下载应用程序的请求。第一个是获取下载 URL,第二个只是调用前一个请求返回的 URL。两个请求中的第一个具有类似 https://firebaseappdistribution-pa.clients6.google.com/v1/{app_name}:getLatestBinary?alt=json&key={api_key} 的地址。 app_name 在获取所有应用程序版本时来自经过身份验证的 session。 api_key 可以从浏览器中复制 URL 或者从第一个请求参数中复制。使用这些参数发送 GET 请求是行不通的,它还需要 cookie 和 headers.

足够headers是:

{
    'origin': 'https://console.firebase.google.com',
    'referer': 'https://console.firebase.google.com/',
    'x-goog-authuser': '<has to be copied from the first request from browser>'
}

说到cookie,事情稍微复杂一些,请求需要以下cookie:“APISID”、“HSID”、“SAPISID”、“SID”和“SSID”。我从第一个请求中复制了它们。那么所缺少的只是一个额外的 cookie:“SAPISIDHASH”,感谢 this answer,我在 python:

中创建了我的实现
def calculate_sapisid_hash(cookies):
    """Calculates SAPISIDHASH based on cookies. Required in authorization to download apk from firebase"""
    epoch = int(time())
    sha = sha1(' '.join([str(int(epoch)), cookies['SAPISID'], 'https://console.firebase.google.com']).encode())
    return f'SAPISIDHASH {int(epoch)}_{sha.hexdigest()}'

最后,通过将“SAPISIDHASH”添加到 cookie,我们可以在第一个 URL 上发送 GET 请求,并获得包含“fileURL”和“文件大小”。有了“fileURL”,我们可以用 requests.get / wget / curl 保存最终文件,因为不需要额外的授权