fix: harden CPA auth flow with API callback/state checks

Move CPA oauth url/callback handling to management API first, persist state/origin runtime keys, and fail fast on invalid callback or missing management auth to reduce flaky panel-driven auth failures.
This commit is contained in:
cnxwzy
2026-04-27 19:13:22 +08:00
parent c98cfd7053
commit f9f8df19d3
12 changed files with 911 additions and 2294 deletions
+11 -25
View File
@@ -40,13 +40,7 @@
return /缺少|未配置|请输入|无效|错误|失败|401|认证失败|未授权|unauthorized|invalid/i.test(message);
}
function getVisibleStep(state, fallback = 7) {
const visibleStep = Math.floor(Number(state?.visibleStep) || 0);
return visibleStep > 0 ? visibleStep : fallback;
}
async function executeStep7(state) {
const visibleStep = getVisibleStep(state, 7);
if (!state.email) {
throw new Error('缺少邮箱地址,请先完成步骤 3。');
}
@@ -60,22 +54,22 @@
try {
const currentState = attempt === 1 ? state : await getState();
const password = currentState.password || currentState.customPassword || '';
const oauthUrl = await refreshOAuthUrlBeforeStep6(currentState, { visibleStep });
const oauthUrl = await refreshOAuthUrlBeforeStep6(currentState);
if (typeof startOAuthFlowTimeoutWindow === 'function') {
await startOAuthFlowTimeoutWindow({ step: visibleStep, oauthUrl });
await startOAuthFlowTimeoutWindow({ step: 7, oauthUrl });
}
const loginTimeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
? await getOAuthFlowStepTimeoutMs(180000, {
step: visibleStep,
step: 7,
actionLabel: 'OAuth 登录并进入验证码页',
oauthUrl,
})
: 180000;
if (attempt === 1) {
await addLog(`步骤 ${visibleStep}:正在打开最新 OAuth 链接并登录...`);
await addLog('步骤 7:正在打开最新 OAuth 链接并登录...');
} else {
await addLog(`步骤 ${visibleStep}:上一轮失败后,正在进行第 ${attempt} 次尝试(最多 ${STEP6_MAX_ATTEMPTS} 次)...`, 'warn');
await addLog(`步骤 7:上一轮失败后,正在进行第 ${attempt} 次尝试(最多 ${STEP6_MAX_ATTEMPTS} 次)...`, 'warn');
}
await reuseOrCreateTab('signup-page', oauthUrl);
@@ -89,14 +83,13 @@
payload: {
email: currentState.email,
password,
visibleStep,
},
},
{
timeoutMs: loginTimeoutMs,
responseTimeoutMs: loginTimeoutMs,
retryDelayMs: 700,
logMessage: `步骤 ${visibleStep}:认证页正在切换,等待页面重新就绪后继续登录...`,
logMessage: '步骤 7:认证页正在切换,等待页面重新就绪后继续登录...',
}
);
@@ -105,16 +98,9 @@
}
if (isStep6SuccessResult(result)) {
const completionPayload = {
await completeStepFromBackground(7, {
loginVerificationRequestedAt: result.loginVerificationRequestedAt || null,
};
if (result.skipLoginVerificationStep) {
completionPayload.skipLoginVerificationStep = true;
}
if (result.directOAuthConsentPage) {
completionPayload.directOAuthConsentPage = true;
}
await completeStepFromBackground(visibleStep, completionPayload);
});
return;
}
@@ -132,7 +118,7 @@
}
if (isManagementSecretConfigError(err)) {
await addLog(
`步骤 ${visibleStep}:检测到来源后台管理密钥缺失或错误,不再重试,当前流程停止。原因:${getErrorMessage(err)}`,
`步骤 7:检测到来源后台管理密钥缺失或错误,不再重试,当前流程停止。原因:${getErrorMessage(err)}`,
'error'
);
throw err;
@@ -142,11 +128,11 @@
break;
}
await addLog(`步骤 ${visibleStep}:第 ${attempt} 次尝试失败,原因:${getErrorMessage(err)};准备重试...`, 'warn');
await addLog(`步骤 7:第 ${attempt} 次尝试失败,原因:${getErrorMessage(err)};准备重试...`, 'warn');
}
}
throw new Error(`步骤 ${visibleStep}:判断失败后已重试 ${STEP6_MAX_ATTEMPTS - 1} 次,仍未成功。最后原因:${getErrorMessage(lastError)}`);
throw new Error(`步骤 7:判断失败后已重试 ${STEP6_MAX_ATTEMPTS - 1} 次,仍未成功。最后原因:${getErrorMessage(lastError)}`);
}
return { executeStep7 };