opencode-codebuddy-external-auth 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/plugin.js +34 -16
  2. package/package.json +1 -1
package/dist/plugin.js CHANGED
@@ -20,9 +20,6 @@ const CONFIG = {
20
20
  function sleep(ms) {
21
21
  return new Promise((resolve) => setTimeout(resolve, ms));
22
22
  }
23
- function generateState() {
24
- return crypto.randomUUID();
25
- }
26
23
  /**
27
24
  * Creates an authenticated fetch function with CodeBuddy headers
28
25
  */
@@ -46,15 +43,37 @@ function createAuthenticatedFetch(accessToken, userId) {
46
43
  // OAuth Flow Implementation (IOA Login)
47
44
  // ============================================================================
48
45
  /**
49
- * Build the login URL for IOA authentication
46
+ * Request auth state from server - the state is generated by server, not client!
47
+ * This matches the behavior of `codebuddy /login` command
50
48
  */
51
- function buildLoginUrl(state) {
49
+ async function requestAuthState() {
50
+ // 构造与 codebuddy CLI 相同的请求
51
+ // codebuddy 输出的 URL: https://copilot.tencent.com/login?platform=CLI&state=xxx&ioa=1
52
52
  const params = new URLSearchParams({
53
53
  platform: CONFIG.platform,
54
- state: state,
55
- ioa: "1", // IOA version flag
54
+ ioa: "1",
55
+ });
56
+ const response = await fetch(`${CONFIG.serverUrl}/plugin/auth/state?${params.toString()}`, {
57
+ method: "GET",
58
+ headers: {
59
+ Accept: "application/json",
60
+ },
56
61
  });
57
- return `${CONFIG.serverUrl}/login?${params.toString()}`;
62
+ if (!response.ok) {
63
+ const text = await response.text();
64
+ throw new Error(`Auth state request failed: ${response.status} - ${text}`);
65
+ }
66
+ const data = await response.json();
67
+ if (!data.data?.state) {
68
+ throw new Error(`Invalid auth state response: ${JSON.stringify(data)}`);
69
+ }
70
+ // 构造登录 URL(与 codebuddy CLI 输出的格式一致)
71
+ const loginUrl = data.data.url ||
72
+ `${CONFIG.serverUrl}/login?platform=${CONFIG.platform}&state=${data.data.state}&ioa=1`;
73
+ return {
74
+ state: data.data.state,
75
+ url: loginUrl,
76
+ };
58
77
  }
59
78
  /**
60
79
  * Poll for token after user completes browser authentication
@@ -70,8 +89,7 @@ async function pollForToken(state, expiresAt, signal) {
70
89
  const response = await fetch(`${CONFIG.serverUrl}/plugin/auth/token?state=${state}`, {
71
90
  method: "GET",
72
91
  headers: {
73
- "Content-Type": "application/json",
74
- "Accept": "application/json",
92
+ Accept: "application/json",
75
93
  },
76
94
  signal,
77
95
  });
@@ -155,17 +173,17 @@ const CodeBuddyExternalAuthPlugin = async (_input) => {
155
173
  label: "IOA 登录 (浏览器)",
156
174
  type: "oauth",
157
175
  async authorize() {
158
- // Generate state for CSRF protection
159
- const state = generateState();
160
- const loginUrl = buildLoginUrl(state);
176
+ // 关键修改:从服务端获取 state,而不是客户端生成
177
+ // 这与 codebuddy CLI 的 /login 命令行为一致
178
+ const authState = await requestAuthState();
161
179
  const expiresAt = Date.now() + 10 * 60 * 1000; // 10 minutes
162
180
  return {
163
- url: loginUrl,
181
+ url: authState.url,
164
182
  instructions: `请在浏览器中完成 IOA 登录`,
165
183
  method: "auto",
166
184
  async callback() {
167
- // Poll for token
168
- const tokenData = await pollForToken(state, expiresAt);
185
+ // 使用服务端返回的 state 轮询 token
186
+ const tokenData = await pollForToken(authState.state, expiresAt);
169
187
  if (!tokenData) {
170
188
  return { type: "failed" };
171
189
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-codebuddy-external-auth",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "OpenCode plugin for CodeBuddy External (IOA) authentication",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",