@lark-project/cli
Version:
飞书项目插件开发工具
89 lines (88 loc) • 3.82 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getToolAuthHeaders = void 0;
const request_1 = require("./request");
const auth_config_1 = require("../v2/utils/auth-config");
const logger_1 = require("../utils/logger");
const require_auth_1 = require("../utils/require-auth");
/**
* Refresh the access token using refresh_token + client_id.
* Aligned with Go CLI's TokenManager.RefreshToken().
* Uses request() to ensure debug headers (x-tt-env, x-use-ppe, etc.) are included.
*/
async function refreshAccessToken(serverUrl, profile) {
if (!profile.refreshToken || !profile.clientId) {
return null;
}
const host = serverUrl.replace(/\/$/, '');
let tokenEndpoint;
try {
const metadata = await (0, request_1.request)(`${host}/.well-known/oauth-authorization-server/b/auth/developer`, { method: 'GET', timeout: 5000 });
tokenEndpoint = (metadata === null || metadata === void 0 ? void 0 : metadata.token_endpoint) || `${host}/goapi/v5/app/developer/oauth/token`;
}
catch (_a) {
tokenEndpoint = `${host}/goapi/v5/app/developer/oauth/token`;
}
try {
const params = new URLSearchParams();
params.append('grant_type', 'refresh_token');
params.append('refresh_token', profile.refreshToken);
params.append('client_id', profile.clientId);
const data = await (0, request_1.request)(tokenEndpoint, {
method: 'POST',
data: params,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
timeout: 10000,
});
if (!(data === null || data === void 0 ? void 0 : data.access_token))
return null;
const now = Math.floor(Date.now() / 1000);
const update = {
accessToken: data.access_token,
accessTokenExpiresAt: data.expires_in ? now + data.expires_in : profile.accessTokenExpiresAt,
refreshToken: data.refresh_token || profile.refreshToken,
refreshTokenExpiresAt: data.refresh_token_expires_in
? now + data.refresh_token_expires_in
: profile.refreshTokenExpiresAt,
tokenId: data.token_id || profile.tokenId,
};
(0, auth_config_1.saveProfile)(serverUrl, update);
return Object.assign(Object.assign({}, profile), update);
}
catch (err) {
logger_1.logger.debug(`Token refresh failed: ${err.message}`);
return null;
}
}
async function getToolAuthHeaders(siteDomain) {
const siteOrigin = new URL(siteDomain).origin;
let profile = (0, auth_config_1.loadEffectiveProfile)(siteOrigin);
if (!profile) {
throw new Error('\n' + (0, require_auth_1.buildAuthGuidance)(siteOrigin));
}
// developerToken is permanent, no refresh needed
if ((0, auth_config_1.hasDeveloperToken)(profile)) {
(0, auth_config_1.touchLastUsed)(siteOrigin);
return {
Authorization: `Bearer ${profile.developerToken}`,
};
}
// OAuth accessToken: auto-refresh if expired
if (!profile.accessToken) {
throw new Error('\n' + (0, require_auth_1.buildAuthGuidance)(siteOrigin));
}
if (profile.accessTokenExpiresAt && Math.floor(Date.now() / 1000) > profile.accessTokenExpiresAt) {
const refreshed = await refreshAccessToken(siteOrigin, profile);
if (refreshed) {
profile = refreshed;
}
else {
throw new Error(`Access token expired and refresh failed for ${siteOrigin}.\n\n` + (0, require_auth_1.buildAuthGuidance)(siteOrigin));
}
}
(0, auth_config_1.touchLastUsed)(siteOrigin);
return {
Authorization: `Bearer ${(0, auth_config_1.resolveToken)(profile)}`,
};
}
exports.getToolAuthHeaders = getToolAuthHeaders;