快速開始
快速開始
用最少的程式碼跑通一次完整的「身份握手」——工作空間使用者點開你的組織擴充應用程式後傳遞身份資訊,讓開發者的擴充應用程式後端能夠正確識別目前使用者身份,取得使用者身份資訊。
- Workspace-Extension-SDK 的 Github 位址為: https://github.com/GPTBOTS/Workspace-Extension-SDK
- 拉式登入見 04-拉式登入。
以下快速教學使用**推式(Push)**模式進行簡單示範:
前置:取得金鑰
你需要先取得組織擴充應用程式的 HS256 簽章金鑰,用來完成組織擴充應用程式的身份握手。
- 讓工作空間的 OWNER/ADMIN 進入 工作空間 → 空間管理 → 擴充應用程式,點「新增」
- 應用程式名稱、應用程式圖示、應用程式入口 URL(
app_home_url) - 驗證模式選 workspace_account(需要傳遞身份)
- 提交後系統一次性明文顯示
App Secret,請立刻複製儲存——關閉後無法再次查看,只能輪換。
金鑰形如
wext_+ 64 位十六進位(Tier 2)。只儲存在你的後端(環境變數 / 金鑰管理服務),絕不寫進前端、git、日誌。
第 1 步:後端 —— 校驗令牌的介面
新建一個後端介面,接收前端 POST 過來的 wsa,用金鑰校驗,成功後建立你自己的工作階段。
// Node / Express 範例
import express from 'express';
import { verifyWsa, WsaVerificationError } from '@gptbots/workspace-extension-verify';
const app = express();
app.use(express.json());
app.post('/session/exchange', (req, res) => {
try {
const identity = verifyWsa(req.body.wsa, {
secret: process.env.EXTENSION_APP_SECRET, // 你的金鑰(只在後端)
audience: 'app.example.com', // 你的應用程式 host,必須等於令牌 aud
});
// identity = { accountId, role, workspaceId, username?, email?, avatar?, appName?, issuedAt?, expiresAt? }
const sid = createYourSession(identity); // 換成你自己的 session
res.cookie('sid', sid, { httpOnly: true, secure: true, sameSite: 'lax' });
res.json(identity);
} catch (e) {
const code = e instanceof WsaVerificationError ? e.code : 'Error';
res.status(401).json({ code }); // 校驗失敗一律拒絕
}
});
// Node / Express 範例
import express from 'express';
import { verifyWsa, WsaVerificationError } from '@gptbots/workspace-extension-verify';
const app = express();
app.use(express.json());
app.post('/session/exchange', (req, res) => {
try {
const identity = verifyWsa(req.body.wsa, {
secret: process.env.EXTENSION_APP_SECRET, // 你的金鑰(只在後端)
audience: 'app.example.com', // 你的應用程式 host,必須等於令牌 aud
});
// identity = { accountId, role, workspaceId, username?, email?, avatar?, appName?, issuedAt?, expiresAt? }
const sid = createYourSession(identity); // 換成你自己的 session
res.cookie('sid', sid, { httpOnly: true, secure: true, sameSite: 'lax' });
res.json(identity);
} catch (e) {
const code = e instanceof WsaVerificationError ? e.code : 'Error';
res.status(401).json({ code }); // 校驗失敗一律拒絕
}
});
此代碼塊在浮窗中顯示
verifyWsa會依序校驗:簽章 →iss→aud→exp(含iat/nbf)→ 必填聲明。任一不過拋WsaVerificationError。詳見 06-SDK-API-參考。
第 2 步:前端 —— 落地頁消費令牌
使用者被平台帶到你的 app_home_url?wsa=<JWT>。在這個落地頁上,讀取 wsa、POST 給你自己的後端、然後從 URL 抹掉它。
// 你的落地頁
import { consumeHandoff } from '@gptbots/workspace-extension-sdk';
const identity = await consumeHandoff({ exchangeUrl: '/session/exchange' });
// consumeHandoff 依序做了:
// 1) 讀取目前 URL 的 ?wsa=
// 2) POST { wsa } 到 /session/exchange(你的後端在這裡 verifyWsa)
// 3) 成功後用 history.replaceState 抹掉 URL 裡的 ?wsa=
// 4) 回傳你後端回傳的 identity
console.log('目前工作空間使用者:', identity.username, identity.role);
if (identity.role === 'MEMBER') hideAdminUI();
// 你的落地頁
import { consumeHandoff } from '@gptbots/workspace-extension-sdk';
const identity = await consumeHandoff({ exchangeUrl: '/session/exchange' });
// consumeHandoff 依序做了:
// 1) 讀取目前 URL 的 ?wsa=
// 2) POST { wsa } 到 /session/exchange(你的後端在這裡 verifyWsa)
// 3) 成功後用 history.replaceState 抹掉 URL 裡的 ?wsa=
// 4) 回傳你後端回傳的 identity
console.log('目前工作空間使用者:', identity.username, identity.role);
if (identity.role === 'MEMBER') hideAdminUI();
此代碼塊在浮窗中顯示
就這樣,兩段程式碼就完成了一次安全的身份握手。
完整鏈路一圖流
工作空間「擴充」頁 GPTBots 平台 你的應用程式
──────────────── ─────────── ────────
使用者點擊你的應用程式圖示 ───────────────▶ 校驗點擊人是該工作空間成員
用金鑰簽一枚 5 分鐘有效的 wsa (JWT)
打開 https://app.example.com/?wsa=<JWT> ────────────────────────────▶ 落地頁
consumeHandoff()
◀── POST /session/exchange { wsa } ──
你的後端 verifyWsa() → identity
建立自有 session
抹掉 URL 裡的 ?wsa=
工作空間「擴充」頁 GPTBots 平台 你的應用程式
──────────────── ─────────── ────────
使用者點擊你的應用程式圖示 ───────────────▶ 校驗點擊人是該工作空間成員
用金鑰簽一枚 5 分鐘有效的 wsa (JWT)
打開 https://app.example.com/?wsa=<JWT> ────────────────────────────▶ 落地頁
consumeHandoff()
◀── POST /session/exchange { wsa } ──
你的後端 verifyWsa() → identity
建立自有 session
抹掉 URL 裡的 ?wsa=
此代碼塊在浮窗中顯示
本地聯調小提示
wsa有效期只有 5 分鐘,是一次性引導令牌——換成自有工作階段後,後續請求不要再帶wsa。audience必須精確等於你註冊的 host(app.example.com),連接埠/協定不參與aud,但 host 必須一致,否則WrongAudience。- 校驗失敗先看
WsaVerificationError.code(InvalidSignature/Expired/WrongAudience…),對照 07-常見問題與排錯。 - 想不建工作階段、只讀取身份用於顯示?把
consumeHandoff換成readHandoffToken()即可(見 02 消費三檔)。
下一步:讀 02-核心概念 理解令牌契約與兩種模式,或直接進 03-推式接入 / 04-拉式登入 看完整細節。
把你自己的 Web 系統作為「擴充應用程式」接入 GPTBots 工作空間。當工作空間使用者從 工作空間 → 擴充 (Extensions) 打開你的應用程式時,GPTBots 會把使用者的工作空間身份以一枚短期簽章令牌(wsa,一個 JWT)安全地交接給你,你的應用程式據此免登入識別使用者、按角色開放功能。
目錄導覽
| 檔案 | 讀者 | 內容 |
|---|---|---|
| 快速開始.md | 所有人 | 10 分鐘跑通一次完整身份握手(含最小可用的前端 + 後端程式碼) |
| 核心概念.md | 所有人 | 兩層擴充應用程式、兩種整合模式、auth_mode、消費三檔、wsa 令牌契約 |
| 推式接入-身份握手.md | 推式接入方 | 使用者在擴充頁點開應用程式 → 平台把 wsa 推給你(?wsa= 落地頁) |
| 拉式登入-Login-with-GPTBots.md | 拉式接入方 | 你的應用程式放一個「Login with GPTBots Workspace」按鈕(OAuth2 授權碼 + PKCE) |
| 令牌校驗與安全.md | 所有人(必讀) | 強制校驗清單、金鑰保管、不用 SDK 時的多語言校驗(Java / Node / Python) |
| SDK-API-參考.md | 所有人 | 兩個 SDK 套件的完整 API、型別、錯誤碼 |
| 常見問題與排錯.md | 所有人 | FAQ、錯誤碼總表、常見坑 |
SDK 一覽
官方 SDK 是框架無關、零執行時相依的兩個套件(都在壓縮檔 workspace-extension-sdk-0.1.0.zip 裡):
| 套件名 | 執行位置 | 作用 |
|---|---|---|
@gptbots/workspace-extension-verify |
你的後端(Node) | 用金鑰校驗 wsa → 得到 WorkspaceIdentity;後端換取 code → wsa |
@gptbots/workspace-extension-sdk |
瀏覽器 | 讀取 / 抹除 / 交換 wsa;發起「Login with GPTBots Workspace」 |
不想用 SDK 也可以——
wsa是標準 HS256 JWT,任意語言的 JWT 函式庫都能校驗。見 05-令牌校驗與安全。
從壓縮檔本地安裝
# 解壓後,兩個套件都自帶預建置 dist,可直接本地相依:
unzip workspace-extension-sdk-0.1.0.zip
npm i ./workspace-extension-sdk/packages/verify # 後端
npm i ./workspace-extension-sdk/packages/browser # 前端
# 解壓後,兩個套件都自帶預建置 dist,可直接本地相依:
unzip workspace-extension-sdk-0.1.0.zip
npm i ./workspace-extension-sdk/packages/verify # 後端
npm i ./workspace-extension-sdk/packages/browser # 前端
此代碼塊在浮窗中顯示
SDK 公開發布到 npm 後,可直接
npm i @gptbots/workspace-extension-verify/npm i @gptbots/workspace-extension-sdk。
接入前對齊清單
- 已確定你已建立組織擴充應用程式並取得對應金鑰
- 已確定整合模式:推式 或 拉式(M-Auth)
-
app_home_url(推式)/redirect_uri的 host(拉式)與註冊資訊完全一致 - 後端已實作
wsa校驗:簽章 +iss+aud+exp四項強制校驗 - 落地後立刻
history.replaceState抹除 URL 中的wsa/code - 已把令牌換成應用程式自有工作階段,後續請求不再透傳
wsa - 應用程式伺服器時鐘已 NTP 同步
