opencode-codebuddy-external-auth
Advanced tools
+69
-12
@@ -12,3 +12,3 @@ "use strict"; | ||
| // 真实对话 API 路径 | ||
| chatCompletionsPath: "/v2/chat/completions", | ||
| chatCompletionsPath: "/v2/plugin/chat/completions", | ||
| // 平台标识 | ||
@@ -43,2 +43,31 @@ platform: "CLI", | ||
| } | ||
| function generateHexId(length) { | ||
| const bytes = Math.ceil(length / 2); | ||
| const buffer = new Uint8Array(bytes); | ||
| if (globalThis.crypto?.getRandomValues) { | ||
| globalThis.crypto.getRandomValues(buffer); | ||
| } | ||
| else { | ||
| for (let i = 0; i < buffer.length; i += 1) { | ||
| buffer[i] = Math.floor(Math.random() * 256); | ||
| } | ||
| } | ||
| return Array.from(buffer) | ||
| .map((b) => b.toString(16).padStart(2, "0")) | ||
| .join("") | ||
| .slice(0, length); | ||
| } | ||
| function buildTraceHeaders() { | ||
| const traceId = generateHexId(32); | ||
| const spanId = generateHexId(16); | ||
| const parentSpanId = generateHexId(16); | ||
| const sampled = "1"; | ||
| return { | ||
| "X-B3-TraceId": traceId, | ||
| "X-B3-ParentSpanId": parentSpanId, | ||
| "X-B3-SpanId": spanId, | ||
| "X-B3-Sampled": sampled, | ||
| b3: `${traceId}-${spanId}-${sampled}-${parentSpanId}`, | ||
| }; | ||
| } | ||
| function decodeJwtPayload(token) { | ||
@@ -209,6 +238,21 @@ try { | ||
| } | ||
| function buildEnterpriseHeaders(accessToken) { | ||
| const tenantId = cachedTenantId || resolveTenantId(accessToken); | ||
| const enterpriseId = cachedEnterpriseId || resolveEnterpriseId(accessToken); | ||
| const resolvedTenantId = tenantId || enterpriseId; | ||
| if (tenantId) | ||
| cachedTenantId = tenantId; | ||
| if (enterpriseId) | ||
| cachedEnterpriseId = enterpriseId; | ||
| const headers = {}; | ||
| if (resolvedTenantId) | ||
| headers["X-Tenant-Id"] = resolvedTenantId; | ||
| if (enterpriseId) | ||
| headers["X-Enterprise-Id"] = enterpriseId; | ||
| return headers; | ||
| } | ||
| async function buildAuthHeaders(accessToken) { | ||
| const payload = decodeJwtPayload(accessToken); | ||
| const roles = payload?.realm_access?.roles || payload?.resource_access?.account?.roles; | ||
| const tenantId = cachedTenantId || resolveTenantId(accessToken); | ||
| let tenantId = cachedTenantId || resolveTenantId(accessToken); | ||
| let enterpriseId = cachedEnterpriseId || resolveEnterpriseId(accessToken); | ||
@@ -223,2 +267,5 @@ const userId = cachedUserId || resolveUserId(accessToken); | ||
| } | ||
| if (!tenantId && enterpriseId) { | ||
| tenantId = enterpriseId; | ||
| } | ||
| if (tenantId) | ||
@@ -250,2 +297,4 @@ cachedTenantId = tenantId; | ||
| const requestId = messageId; | ||
| const traceHeaders = buildTraceHeaders(); | ||
| const encodedUserId = userId ? encodeURIComponent(userId) : ""; | ||
| const headers = { | ||
@@ -267,2 +316,3 @@ "Accept": "application/json", | ||
| "User-Agent": `CLI/${CONFIG.appVersion} CodeBuddy/${CONFIG.appVersion}`, | ||
| ...traceHeaders, | ||
| }; | ||
@@ -273,4 +323,4 @@ if (tenantId) | ||
| headers["X-Enterprise-Id"] = enterpriseId; | ||
| if (userId) | ||
| headers["X-User-Id"] = userId; | ||
| if (encodedUserId) | ||
| headers["X-User-Id"] = encodedUserId; | ||
| return headers; | ||
@@ -513,3 +563,3 @@ } | ||
| if ((response.status === 401 || response.status === 403) && auth.refresh) { | ||
| const refreshed = await refreshAccessToken(auth.refresh); | ||
| const refreshed = await refreshAccessToken(auth.refresh, accessToken); | ||
| if (refreshed?.accessToken) { | ||
@@ -727,11 +777,18 @@ accessToken = refreshed.accessToken; | ||
| */ | ||
| async function refreshAccessToken(refreshToken) { | ||
| async function refreshAccessToken(refreshToken, accessToken) { | ||
| try { | ||
| const traceHeaders = buildTraceHeaders(); | ||
| const headers = { | ||
| "Content-Type": "application/json", | ||
| "Accept": "application/json", | ||
| "X-Refresh-Token": refreshToken, | ||
| ...traceHeaders, | ||
| }; | ||
| if (accessToken) { | ||
| headers["Authorization"] = `Bearer ${accessToken}`; | ||
| Object.assign(headers, buildEnterpriseHeaders(accessToken)); | ||
| } | ||
| const response = await fetch(`${CONFIG.serverUrl}/v2/plugin/auth/token/refresh`, { | ||
| method: "POST", | ||
| headers: { | ||
| "Content-Type": "application/json", | ||
| "Accept": "application/json", | ||
| "Authorization": `Bearer ${refreshToken}`, | ||
| }, | ||
| headers, | ||
| }); | ||
@@ -778,3 +835,3 @@ if (!response.ok) { | ||
| } | ||
| const tokenData = await refreshAccessToken(auth.refresh); | ||
| const tokenData = await refreshAccessToken(auth.refresh, auth.access); | ||
| if (!tokenData) { | ||
@@ -781,0 +838,0 @@ return null; |
+1
-1
| { | ||
| "name": "opencode-codebuddy-external-auth", | ||
| "version": "1.0.21", | ||
| "version": "1.0.22", | ||
| "description": "OpenCode plugin for CodeBuddy External (IOA) authentication", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 5 instances in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 5 instances in 1 package
38788
5.37%893
6.82%