opencode-codebuddy-external-auth 1.0.3 → 1.0.4
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.
- package/dist/plugin.js +34 -16
- package/package.json +1 -1
package/dist/plugin.js
CHANGED
|
@@ -44,19 +44,27 @@ function createAuthenticatedFetch(accessToken, userId) {
|
|
|
44
44
|
// ============================================================================
|
|
45
45
|
/**
|
|
46
46
|
* Request auth state from server - the state is generated by server, not client!
|
|
47
|
-
*
|
|
47
|
+
*
|
|
48
|
+
* 关键发现:
|
|
49
|
+
* 1. 使用 POST 方法,不是 GET
|
|
50
|
+
* 2. 路径是 /v2/plugin/auth/state,不是 /plugin/auth/state
|
|
51
|
+
* 3. 需要设置 X-No-Authorization 等 Headers
|
|
48
52
|
*/
|
|
49
53
|
async function requestAuthState() {
|
|
50
|
-
// 构造与 codebuddy CLI 相同的请求
|
|
51
|
-
// codebuddy 输出的 URL: https://copilot.tencent.com/login?platform=CLI&state=xxx&ioa=1
|
|
52
54
|
const params = new URLSearchParams({
|
|
53
55
|
platform: CONFIG.platform,
|
|
54
56
|
ioa: "1",
|
|
55
57
|
});
|
|
56
|
-
const response = await fetch(`${CONFIG.serverUrl}/plugin/auth/state?${params.toString()}`, {
|
|
57
|
-
method: "
|
|
58
|
+
const response = await fetch(`${CONFIG.serverUrl}/v2/plugin/auth/state?${params.toString()}`, {
|
|
59
|
+
method: "POST", // 关键:使用 POST 方法
|
|
58
60
|
headers: {
|
|
59
|
-
Accept: "application/json",
|
|
61
|
+
"Accept": "application/json",
|
|
62
|
+
"Content-Type": "application/json",
|
|
63
|
+
// 这些 Headers 告诉服务端跳过认证检查
|
|
64
|
+
"X-No-Authorization": "true",
|
|
65
|
+
"X-No-User-Id": "true",
|
|
66
|
+
"X-No-Enterprise-Id": "true",
|
|
67
|
+
"X-No-Department-Info": "true",
|
|
60
68
|
},
|
|
61
69
|
});
|
|
62
70
|
if (!response.ok) {
|
|
@@ -64,11 +72,11 @@ async function requestAuthState() {
|
|
|
64
72
|
throw new Error(`Auth state request failed: ${response.status} - ${text}`);
|
|
65
73
|
}
|
|
66
74
|
const data = await response.json();
|
|
67
|
-
if (!data.data?.state) {
|
|
75
|
+
if (data.code !== 0 || !data.data?.state) {
|
|
68
76
|
throw new Error(`Invalid auth state response: ${JSON.stringify(data)}`);
|
|
69
77
|
}
|
|
70
|
-
//
|
|
71
|
-
const loginUrl = data.data.
|
|
78
|
+
// 使用服务端返回的 authUrl,或构造默认 URL
|
|
79
|
+
const loginUrl = data.data.authUrl ||
|
|
72
80
|
`${CONFIG.serverUrl}/login?platform=${CONFIG.platform}&state=${data.data.state}&ioa=1`;
|
|
73
81
|
return {
|
|
74
82
|
state: data.data.state,
|
|
@@ -77,6 +85,8 @@ async function requestAuthState() {
|
|
|
77
85
|
}
|
|
78
86
|
/**
|
|
79
87
|
* Poll for token after user completes browser authentication
|
|
88
|
+
*
|
|
89
|
+
* 注意:token 端点也需要使用 /v2 前缀
|
|
80
90
|
*/
|
|
81
91
|
async function pollForToken(state, expiresAt, signal) {
|
|
82
92
|
const pollInterval = 3000; // 3 seconds
|
|
@@ -86,16 +96,20 @@ async function pollForToken(state, expiresAt, signal) {
|
|
|
86
96
|
}
|
|
87
97
|
await sleep(pollInterval);
|
|
88
98
|
try {
|
|
89
|
-
const response = await fetch(`${CONFIG.serverUrl}/plugin/auth/token?state=${state}`, {
|
|
99
|
+
const response = await fetch(`${CONFIG.serverUrl}/v2/plugin/auth/token?state=${state}`, {
|
|
90
100
|
method: "GET",
|
|
91
101
|
headers: {
|
|
92
|
-
Accept: "application/json",
|
|
102
|
+
"Accept": "application/json",
|
|
103
|
+
"X-No-Authorization": "true",
|
|
104
|
+
"X-No-User-Id": "true",
|
|
105
|
+
"X-No-Enterprise-Id": "true",
|
|
106
|
+
"X-No-Department-Info": "true",
|
|
93
107
|
},
|
|
94
108
|
signal,
|
|
95
109
|
});
|
|
96
110
|
if (response.ok) {
|
|
97
111
|
const data = await response.json();
|
|
98
|
-
if (data.data?.accessToken) {
|
|
112
|
+
if (data.code === 0 && data.data?.accessToken) {
|
|
99
113
|
return data.data;
|
|
100
114
|
}
|
|
101
115
|
}
|
|
@@ -115,11 +129,12 @@ async function pollForToken(state, expiresAt, signal) {
|
|
|
115
129
|
*/
|
|
116
130
|
async function refreshAccessToken(refreshToken) {
|
|
117
131
|
try {
|
|
118
|
-
const response = await fetch(`${CONFIG.serverUrl}/plugin/auth/token/refresh`, {
|
|
132
|
+
const response = await fetch(`${CONFIG.serverUrl}/v2/plugin/auth/token/refresh`, {
|
|
119
133
|
method: "POST",
|
|
120
134
|
headers: {
|
|
121
135
|
"Content-Type": "application/json",
|
|
122
|
-
|
|
136
|
+
"Accept": "application/json",
|
|
137
|
+
"Authorization": `Bearer ${refreshToken}`,
|
|
123
138
|
},
|
|
124
139
|
});
|
|
125
140
|
if (!response.ok) {
|
|
@@ -127,6 +142,10 @@ async function refreshAccessToken(refreshToken) {
|
|
|
127
142
|
return null;
|
|
128
143
|
}
|
|
129
144
|
const data = await response.json();
|
|
145
|
+
if (data.code !== 0) {
|
|
146
|
+
console.warn(`[codebuddy-external] Token refresh error: ${data.msg}`);
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
130
149
|
return data.data || null;
|
|
131
150
|
}
|
|
132
151
|
catch (error) {
|
|
@@ -173,8 +192,7 @@ const CodeBuddyExternalAuthPlugin = async (_input) => {
|
|
|
173
192
|
label: "IOA 登录 (浏览器)",
|
|
174
193
|
type: "oauth",
|
|
175
194
|
async authorize() {
|
|
176
|
-
//
|
|
177
|
-
// 这与 codebuddy CLI 的 /login 命令行为一致
|
|
195
|
+
// 从服务端获取 state(服务端生成,非客户端)
|
|
178
196
|
const authState = await requestAuthState();
|
|
179
197
|
const expiresAt = Date.now() + 10 * 60 * 1000; // 10 minutes
|
|
180
198
|
return {
|