Operit GitHub OAuth Broker 云端交换协议:PKCE 短期认证事务与一次性领取凭据实战解析

发布时间:2026/9/27 7:41:08

Operit GitHub OAuth Broker 云端交换协议:PKCE 短期认证事务与一次性领取凭据实战解析 AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆【免费下载链接】OperitThe most powerful AI agent and AI chat software on Android/Operit是一款Android上能力最为强大、发展最久的AI Agent项目地址https://gitcode.com/gh_mirrors/op/Operit点击查看免费下载导读本文围绕 Operit 项目中docs/TODO/github_oauth_broker/1_CloudBroker.md所定义的云端交换协议展开讲解 Operit 如何把 GitHub OAuth 的授权码交换从 Android 设备端迁移到api.operit.app的受保护 Worker并用 PKCE verifier、一次性领取凭据claim credential与短期认证事务构建设备不接触 client secret、敏感凭据不落地浏览器 URL的登录链路。读完本文你将掌握该协议的事务创建、完成回调、单次领取三阶段设计以及它在 Android 与 Operit 2Rust CLI / Flutter两代客户端中的落地方式并可直接对照仓库源码复现每一条安全边界。背景client secret 为何不能留在 APK 里在进入新协议之前先看旧实现为什么必须被替换。docs/TODO/github_oauth_broker/index.md记录了这次改造的直接动因Android 客户端曾将 GitHub OAuth client secret 写入 BuildConfig并在设备上直接交换授权码。该 secret 随已发布 APK 分发不能继续作为可信凭据。这是移动端 OAuth 的经典悖论APK 可以轻易被反编译编入 BuildConfig 的 client secret 等同于公开同时授权码在设备端换取 token意味着任何能读到 APK 的人都能冒充客户端完成同样的交换。旧协议里设备向 GitHub 直接提交 OAuth 授权码和编入 APK 的 client secret见 1_CloudBroker.md因此被判定为不可继续使用。改造目标被明确写进 index.md新版 Android 只通过api.operit.app的受保护 Worker 完成 GitHub 授权码交换新 APK 不再包含 client ID、client secret 或operit://OAuth 回调已发布的旧 APK 继续使用原 OAuth App直至发布公告规定的迁移截止日新 OAuth App 的 client secret 只存在于 Cloudflare Worker secret。其中最后一条是整套协议的安全基石secret 只存在于云端设备端永远拿不到。旧实现凭据落地的三种路径1_CloudBroker.md与配套的 2_AndroidClient.md、3_Operit2Client.md 共同勾勒了改造前的全貌主要有三条路径客户端旧实现方式安全问题AndroidGitHub 登录界面提供内嵌 WebView 与外部浏览器两条路径应用接收operit://github-oauth-callback后直接向 GitHub 交换 token授权码经自定义 scheme 回传client secret 在设备上参与交换Rust CLIOperit 2使用 GitHub Device Flow并要求操作者设置 GitHub OAuth client ID 环境变量凭据进入环境变量流程与浏览器式授权割裂Flutter 市场页Operit 2要求用户创建并粘贴 GitHub Token用户长期令牌被手动粘贴进客户端风险面大旧 Android 实现的另一个隐患是自定义 scheme 与 Activity Intent 接管operit://github-oauth-callback这样的 scheme 属于全局可声明标识存在被其他应用抢占的风险同时浏览器回调 URL 会真实携带授权码。新协议的目标之一就是把授权码、token 和领取凭据全部排除在浏览器回调 URL 之外见 1_CloudBroker.md 的结果清单。新协议核心短期认证事务三阶段新实现的协议骨架定义在 1_CloudBroker.mdWorker 创建短期认证事务生成 PKCE verifier 与一次性领取凭据。GitHub 回调由 Worker 接收并交换授权码用户 token 加密暂存后重定向到浏览器回调 Host 预先注册的完成地址Core 校验完成链接后以领取凭据 claim 一次记录随即删除。把这段话拆解为三个阶段的时序事务创建start客户端向 Worker 提交自己准备的回调完成地址completion redirect URIWorker 创建短期认证事务生成 PKCE verifier 与一次性领取凭据delivery credential返回授权页面 URL、事务 ID、凭据与过期时间授权与回调complete用户浏览器访问 GitHub 授权页授权码回调由 Worker 接收并完成 PKCE 交换获取的 token 在 Worker 侧加密暂存随后把浏览器重定向到客户端预注册的完成地址完成链接中只携带事务状态单次领取claim客户端Core校验完成链接与当前事务匹配后用一次性领取凭据 claim 一次Worker 返回 token 与用户信息服务端记录随即删除。这套设计同时满足四个约束对应 1_CloudBroker.md 的结果client secret 不离开 Cloudflare secret不落入 APK、不进入请求体授权码、token 和领取凭据不出现在浏览器回调 URL 中回调 URL 只携带transactionId与status等非敏感参数完成通知不产生 Worker 轮询请求客户端一次 start、一次 claim没有状态轮询新接口不改动旧客户端使用的/market/v2/auth/github市场旧接口保持兼容。协议责任划分3_Operit2Client.md 的协议责任进一步明确了边界Worker 持有 OAuth client secret、生成 PKCE 和处理 GitHub 回调客户端不包含 client ID 或 client secretFlutter 市场页不持有 OAuth HTTP、平台 Intent、EventChannel 或 loopback receiver只管理自己的可见 WebView 导航客户端不向 Worker 反复查询授权状态Rust 解析和校验 Broker 响应并以单元测试固定协议契约。客户端协议实现Broker Service 与 Coordinator云端 Worker 的行为无法在本仓库直接查看后端位于独立的marketWorker 工程但 Android 端的协议实现完整存在于本仓库可以直接对照。1.GitHubOAuthBrokerService协议的两个 HTTP 端点GitHubOAuthBrokerService.kt 是客户端侧与 Worker 通信的唯一入口基地址硬编码为https://api.operit.app见 L144。它封装了两个请求startLogin(completionRedirectUri)L60-L82POST$BROKER_BASE_URL/oauth/github/start请求体为{completionRedirectUri: ...}解析返回GitHubOAuthBrokerStartResponse该响应携带transactionId、deliveryCredential、authorizationUrl、completionRedirectUri与expiresAtL18-L25。客户端拿到后即可展示授权页同时本地私有保存领取凭据claimLogin(transactionId, deliveryCredential)L84-L128POST$BROKER_BASE_URL/oauth/github/claim请求体为{transactionId: ..., deliveryCredential: ...}。响应status必须为complete否则拒绝L108-L112随后解出accessToken、tokenType、scope、expiresIn、refreshToken与userL113-L122。两个请求都使用 30 秒超时的 OkHttpClientL49-L53错误统一封装为IllegalStateException并附带 HTTP 状态码与响应体便于排查L130-L136。响应解析使用ignoreUnknownKeys的宽松 Json 配置L55-L58保证前后端字段演进时旧客户端不因多余字段崩溃。2.GitHubOAuthCoordinator事务生命周期管理GitHubOAuthCoordinator.kt 是客户端侧的编排中枢startLogin(completionRedirectUri)L18-L33调用 Broker Service 创建事务并把transactionId、deliveryCredential、expiresAt通过GitHubAuthPreferences.saveActiveOAuthTransaction写入本地 DataStore随后返回事务供 UI 展示授权页completeLogin(completionUri)L35-L82先校验完成链接的transactionId与当前活动事务一致L39-L41否则直接失败随后按status参数分流——complete继续领取、denied视为用户取消并清事务、error透传错误信息、其余视为非法状态确认完成后调用claimLogin领取一次 token保存认证信息并清除活动事务cancelLogin()L84-L86用户取消时清空活动事务避免遗留凭据被复用。值得注意的细节内嵌登录使用固定完成地址https://api.operit.app/oauth/github/completeL90而外部浏览器登录则使用 loopback 临时地址见下文两者都会在 start 时预注册给 Worker对应文档中重定向到浏览器回调 Host 预先注册的完成地址。3. 事务凭据的持久化GitHubAuthPreferencesGitHubAuthPreferences.kt 基于 DataStoregithub_auth_preferencesL19-L20管理全部 GitHub 认证状态。与本次改造直接相关的设计有认证版本门槛REQUIRED_AUTH_VERSION 3L43isAuthSessionCurrentL90-L94要求本地会话的auth_version 3且授予 scope 覆盖notifications,public_repo,user:email,read:userL42旧版本认证数据不会被新认证代码继续使用呼应 2_AndroidClient.md 的认证版本升级旧 APK 数据不会被新版认证代码继续使用活动事务三键active_oauth_transaction_id、active_oauth_delivery_credential、active_oauth_expires_atL55-L57getActiveOAuthTransactionL245-L258在读回时会检查过期并自动清除杜绝过期凭据被 claim领取后清理saveAuthInfoL131-L165在写入 token 的同时移除活动事务三键与服务端记录随即删除形成两端对称的单次语义。Android 登录 UI通用浏览器回调组件与双路径GitHubLoginDialog.kt 保留了内嵌 WebView与外部浏览器两条登录路径L50-L54 的GitHubLoginMode三态CHOOSER / EMBEDDED / EXTERNAL但底层机制全部替换。内嵌路径BrowserCallbackDialog通用组件内嵌登录不再持有 GitHub 协议逻辑而是复用通用组件 BrowserCallbackDialog.kt注释明确写着 Presents one host-owned browser flow and reports navigation to its registered callback destination。它只负责三件事加载authorizationUrlL109-L111在shouldOverrideUrlLoading与onPageStarted两个时机捕获导航L79-L95用matchesCallbackDestinationL189-L194按scheme / host / port / path 四元组匹配完成地址命中即回调onCompletion(uri)并stopLoading()处理超时与释放expiresAt到期未完成则回调onFailureL113-L127releaseBrowserCallbackWebViewL197-L208在释放时依次执行停止加载、about:blank、清历史、移除视图、destroy()避免 WebView 泄漏。由于完成地址是https://api.operit.app/oauth/github/complete这样的 https 地址而非自定义 scheme2_AndroidClient.md 的结果清单中的三项随之成立删除旧自定义 scheme、外部浏览器回调和 Activity Intent 接管浏览器回调组件不包含 GitHub 协议、token 或领取凭据删除 Android 的 client ID 与 client secret BuildConfig 字段。外部路径一次性 loopback 接收器外部浏览器登录使用 GitHubOAuthLoopbackCallbackServer.kt 在127.0.0.1上临时监听一个端口要求端口号 1024L98、L112-L114完成地址为http://127.0.0.1:port/oauth/github/completeL15-L22。awaitCompletionL24-L40只接受一次 GET 请求校验路径与完成地址一致L63-L66把查询参数拼接回完成 URI 后返回 200其余请求返回 404。整个流程在 GitHubLoginDialog.kt 的GitHubExternalLoginDialog中L240-L301用withTimeout(remainingMillis)包裹超时即按登录失败处理finally中关闭服务器并清理事务——这与文档完成通知不产生 Worker 轮询请求的约束一致因为整个链路只有一次授权页展示和一次完成回调。登出与会话隔离2_AndroidClient.md 还规定了一个易被忽略的体验细节用户明确退出 GitHub 登录时应用会清除自身 WebView 的 Cookie 和 WebStorage再删除本地认证信息。下一次登录不会静默复用之前的 GitHub Web 会话这不会影响系统浏览器或 Chrome 的 GitHub 登录状态。即退出登录需要同时清 WebView 会话与本地认证数据但作用域严格限定在应用自身 WebView避免误伤系统浏览器中用户已登录的 GitHub 账号。Operit 2 客户端迁移类型化服务替代命令字符串Operit 2Rust CLI 与 Flutter 市场的迁移方向与 Android 一致但多了一个架构约束3_Operit2Client.md 要求两端都调用 Core 的类型化GitHubOAuthBrokerServiceFlutter 使用生成的 Dart proxy、CLI 使用生成的 Rust proxy两者都不传递市场认证命令字符串、不解析命令 stdout也不手写 CoreLink 请求。具体分工应用自己准备完成地址Core 用该地址调用 Worker 的/oauth/github/start并私有保存 delivery credential应用展示授权页并交回完成链接——CLI 使用临时 loopback 并在终端打印授权链接Flutter 市场登录对话框拦截其 WebView 的完成导航Core 只在收到与当前事务、目标地址都匹配的完成链接后 claim 一次并保存 Worker 返回的 GitHub tokenRust 侧通过单元测试固定协议契约Rust 解析和校验 Broker 响应并以单元测试固定协议契约。这条迁移路径的意图很清晰旧实现里 CLI 依赖环境变量 client ID、Flutter 要求用户粘贴 token、两端以命令字符串与 stdout 解析方式对接市场认证都属于凭据或协议细节外泄的脆弱设计新实现把协议收敛为类型化的 start/claim 调用凭据只在 Core 与 Worker 之间传递。结果清单与安全收益汇总综合 1_CloudBroker.md 与 2_AndroidClient.md 的结果章节本次改造的验收标准如下client secret 不离开 Cloudflare secret任何客户端二进制与请求体中都不可见授权码、token 和领取凭据不出现在浏览器回调 URL 中回调 URL 仅携带事务 ID 与状态完成通知不产生 Worker 轮询请求全链路仅 start / claim 两次 HTTP 往返新接口不改动旧客户端使用的/market/v2/auth/github旧接口保持兼容直至迁移截止日Android 删除旧自定义 scheme、外部浏览器回调和 Activity Intent 接管浏览器回调组件不含 GitHub 协议、token 或领取凭据Android 删除 client ID 与 client secret 的 BuildConfig 字段认证版本升级到 3旧 APK 数据不会被新认证代码继续使用。从实现事实看这些收益都能在本仓库的源码中得到印证GitHubOAuthBrokerService的请求体只有completionRedirectUri/transactionId/deliveryCredentialGitHubOAuthBrokerService.kt没有任何 client secret 字段完成链接校验依赖transactionId与状态参数GitHubOAuthCoordinator.kt仓库中已搜不到operit://github-oauth-callback或 client secret BuildConfig 字段的残留。部署顺序与现状index.md 的状态章节记录了该改造的推进节奏云端密钥已配置、新 OAuth App 已创建、D1 迁移已应用Worker 部署待后端现有未提交市场改动整理后执行Operit 2 客户端迁移进行中CLI 包当时的编译问题与本协议无关。部署顺序明确为后端先于 Android——这是合理的依赖顺序新 APK 依赖 Worker 的/oauth/github/start与/oauth/github/claim端点云端必须先就绪旧客户端才能继续使用原 OAuth App 平稳过渡到迁移截止日。对读者而言若要在自己的项目里复刻这套方案最小可复制的骨架是一台持有 client secret 的云端 Worker负责 PKCE 与授权码交换、一个短期事务存储带过期与单次领取语义、客户端侧一次 start 一次 claim 的类型化调用以及一个只按 scheme/host/port/path 匹配完成地址的通用浏览器回调组件。Operit 的 GitHubOAuthBrokerService.kt 与 GitHubOAuthCoordinator.kt 提供了现成的参考实现。赞分享AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆【免费下载链接】OperitThe most powerful AI agent and AI chat software on Android/Operit是一款Android上能力最为强大、发展最久的AI Agent项目地址https://gitcode.com/gh_mirrors/op/Operit点击查看免费下载相关推荐Operit GitHub OAuth 完成回调协议Worker 事务、应用自持浏览器与一次性 Claim 的完整交付链路Operit GitHub OAuth 完成回调协议Worker 事务、应用自持浏览器与一次性 Claim 的完整交付链路 本指南围绕 Operit 仓库中AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆GUI 自动化MCP Toolbox 之 oceanbase-execute-sql在 OceanBase 上执行 SQL 的 MCP 工具配置与实战指南MCP Toolbox 之 oceanbase execute sql在 OceanBase 上执行 SQL 的 MCP 工具配置与实战指南 oceanbasAI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆GUI 自动化Open edX 认证凭证交换实战auth_exchange 模块的第三方 OAuth 接入与 Token 登录实现Open edX 认证凭证交换实战auth_exchange 模块的第三方 OAuth 接入与 Token 登录实现 导读 本文以 Open edX 平台后端教育上一篇深入解析mshumer/gpt-author项目AI自动生成小说全流程指南下一篇从0到1使用Google Workspace MCP Server构建自动化邮件处理系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/27 7:41:08

Puppet device 子命令实战指南:用 proxy agent 管理远程网络设备

运维DevOpsIaC 【免费下载链接】puppet Server automation framework and application 项目地址: https://gitcode.com/gh_mirrors/pu/puppet 点击查看 免费下载 导读 puppet device 是 Puppet 项目中专门用于管理远程网络设备(交换机、路由器等无法直…

2026/9/27 7:36:08

HRTOS实战:8051使用超声波模块实现距离测量并通过数码管显示

在前面的实例中,我们已经使用HRTOS完成了红外避障和雨滴传感器应用。本文继续介绍一个常见的8051传感器应用:超声波测距。本例使用超声波模块测量目标距离,并将测量结果以毫米(mm)为单位显示在4位数码管上。例如&#…

2026/9/27 8:26:10

开源作者的自我修养:保持更新与长期主义

开源作者的自我修养:保持更新与长期主义在开源社区中,最常见的景象是:一个项目在刚发布的前两周万众瞩目,收获了数百上千个 Star;但三个月后,维护者的热情消退,仓库里堆满了无人理睬的 Issue&am…

2026/9/27 8:26:10

别再把它们搞混了!传统 AI vs Agent:一文讲透本质区别

前言:一个真实场景,两种截然不同的结局 上周我让 AI 帮我做同一件事:“分析一下我们上季度的销售数据,找出下滑原因,出一份报告。” 传统 AI(ChatGPT 对话框)的结局: 我导出 CSV&…

2026/9/27 0:00:45

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/9/27 0:00:45

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/27 0:00:45

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/27 0:00:45

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/9/27 0:00:45

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/27 0:00:45

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/25 20:55:38

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/26 19:58:38

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/25 18:34:56

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑