平台应用授权与 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 = S256SDK 把 codeVerifier 和 state 临时保存在当前浏览器会话中,不会把 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 | 是 | 授权完成后的回跳地址,必须与应用入口同源 |
codeChallenge | 是 | PKCE challenge |
codeChallengeMethod | 是 | 使用 S256 |
state | 是 | 防止请求伪造和回跳串线的随机值 |
旧参数 prompt 和 authorizationRequestToken 已退役,应用不得发送。
第三步:处理回跳
网页授权成功后回跳 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_APPLICATION 或 RUNTIME_APP 两套 scope;所有通过
Bundle 安装的平台应用都使用同一 Runtime 绑定 token 契约。
授权码只能使用一次。兑换失败、token 到期或服务返回未授权时,应清理当前安装的本地会话并重新开始授权流程。
不要把 token 放在回跳 URL
URL 会进入浏览器历史、Referer、代理和访问日志。网页授权页只回传一次性授权码,最终 appClientToken 必须通过后端 token exchange 响应取得。