百积木文档
开发指南平台应用、模块与 Bundle 开发平台应用开发

平台应用授权与 PKCE

Bundle 安装的环境托管平台应用通过同源配置、统一网页授权和 PKCE 获取 appClientToken。

ENVIRONMENT_HOSTED_APP 必须通过 @baijimu/platform-application-sdk 使用当前部署提供的统一网页授权页。 公共 SaaS 当前地址是:

https://console.baijimu.com/#/platform-app-authorize

这个地址只是公共 SaaS 的部署值,不是 SDK 默认值。SDK 从当前托管应用同源的 /.well-known/baijimu-platform-application.json 读取各环境登记的授权地址。 历史 TRUSTED_EXTERNAL_APP 已被当前启动和平台授权链路拒绝,外部站点必须使用自己的后台授权; 需要平台能力的应用先迁移为环境托管并升级 Bundle。 应用不能自己复制网页授权页、复制一份 sdk.js,也不能直接调用内部授权接口并传入 userId。 平台授权页负责确认登录态、工作区访问权,以及平台应用是否来自当前工作区已启用的精确 Bundle 安装; 标准 SDK 负责发起授权请求、处理回跳和兑换 token。

这里的 token 兑换属于 App Gateway 平台应用授权链路。完整接入配置见 App Gateway 接入与配置

完整流程

工作区打开 accessUrl
  -> SDK 读取 installId
  -> SDK 生成 codeVerifier、codeChallenge 和 state
  -> SDK 跳转部署配置中的平台网页授权页
  -> 平台校验工作区成员、Bundle 安装和版本声明
  -> 授权页回跳 redirectUri,携带一次性 code
  -> SDK 校验 state
  -> SDK 使用 code + codeVerifier 兑换并校验 appClientToken
  -> SDK 携带 Bearer token 调用授权范围内的接口

这一步没有独立的平台应用 consent 确认。能力范围来自当前 Bundle 安装锁定的平台应用版本;扩大能力时必须创建新版本并升级 Bundle,而不是让前端提交一份新的授权范围。

分享入口与未安装提示

使用 baijimu platform-app entry <platformAppId> --bundle-id <bundleId> --json 查询当前环境的通用入口。 不要直接把带某个工作区 installId 的应用启动地址分享给其他用户。标准分享地址是:

https://console.baijimu.com/#/bundle-app/{bundleId}/{platformAppId}

接收者登录后选择有权访问的工作区。Manager 会按 bundleId + platformAppId 核验该工作区的精确安装资源:

  • 已安装且应用已启用:直接进入工作区应用入口。
  • 未安装:明确提示需要安装该 Bundle,并进入只显示目标 Bundle 的安装流程;安装完成后返回原分享入口。
  • 已物化但未启用:不签发授权码,提示工作区管理员检查 Bundle 安装状态。
  • 当前成员不能安装:保留安装需求,由工作区所有者或管理员执行。

公开访问应用页面不代表拥有安装权限;installId 只是安装选择器,不能用于证明访问权或换取平台 token。

第一步:生成 PKCE 参数

应用只调用 client.bootstrap()。SDK 会为每次授权生成新的高熵 codeVerifier,并使用 SHA-256 计算 Base64 URL 编码的 codeChallenge

codeChallenge = BASE64URL(SHA256(codeVerifier))
codeChallengeMethod = S256

SDK 把 codeVerifierstate 临时保存在当前浏览器会话中,不会把 codeVerifier 放进 URL。

第二步:跳转网页授权页

公共 SaaS 授权页使用 Hash Router,因此 SDK 会把授权参数写在 #/platform-app-authorize 后面的查询 字符串中:

https://console.baijimu.com/#/platform-app-authorize
  ?installId=pia_xxx
  &redirectUri=https%3A%2F%2Fapp.example.com%2F
  &codeChallenge=...
  &codeChallengeMethod=S256
  &state=...

参数含义:

参数是否必填说明
installId当前工作区安装记录
redirectUri授权完成后的回跳地址,必须与应用入口同源
codeChallengePKCE challenge
codeChallengeMethod使用 S256
state防止请求伪造和回跳串线的随机值

旧参数 promptauthorizationRequestToken 已退役,应用不得发送。

第三步:处理回跳

网页授权成功后回跳 redirectUri,并附加:

?code=一次性授权码&installId=pia_xxx&state=原始state

回跳携带的是短期、一次性 code,不是最终 token。SDK 会先验证 state 与发起授权时保存的值一致, 再执行兑换。

第四步:兑换 token

SDK 调用当前部署配置中的 App Gateway。公共 SaaS 对应的请求示例是:

POST https://api.baijimu.com/app-gateway/api/workspace-runtime/apps/{installId}/token/exchange
Content-Type: application/json

{
  "code": "authorization-code",
  "codeVerifier": "original-code-verifier"
}

兑换成功后 SDK 会校验:

  • 返回的 workspaceId 是有效工作区
  • 返回的 runtimeAppId 与当前安装绑定的默认 Runtime 应用一致
  • token 对应的 installId 与启动安装一致
  • token 尚未过期

App Gateway 将 token 放在响应的 data.token 中。应用通过同源配置初始化标准 SDK,不能把公共 SaaS 地址 或 URL 中未验证的参数作为授权服务地址:

import { createPlatformApplicationClientFromHostedConfiguration } from "@baijimu/platform-application-sdk";

const client = await createPlatformApplicationClientFromHostedConfiguration(applicationDefinition.id);

appClientToken 没有 PLATFORM_APPLICATIONRUNTIME_APP 两套 scope;所有通过 Bundle 安装的平台应用都使用同一 Runtime 绑定 token 契约。

授权码只能使用一次。兑换失败、token 到期或服务返回未授权时,应清理当前安装的本地会话并重新开始授权流程。

不要把 token 放在回跳 URL

URL 会进入浏览器历史、Referer、代理和访问日志。网页授权页只回传一次性授权码,最终 appClientToken 必须通过后端 token exchange 响应取得。

本页内容