拆分 OAuth 后置验证流程

This commit is contained in:
QLHazyCoder
2026-05-15 23:03:02 +08:00
parent 4c2ab31b07
commit 3f3f9275cc
26 changed files with 1578 additions and 584 deletions
+53 -31
View File
@@ -9596,6 +9596,9 @@ const AUTO_RUN_BACKGROUND_COMPLETED_STEP_KEYS = new Set([
'plus-checkout-return',
'oauth-login',
'fetch-login-code',
'post-login-phone-verification',
'bind-email',
'fetch-bind-email-code',
'confirm-oauth',
]);
const STEP_COMPLETION_SIGNAL_STEP_KEYS = new Set([
@@ -10047,6 +10050,9 @@ async function waitForRunningStepsToFinish(payload = {}) {
const AUTH_CHAIN_NODE_IDS = new Set([
'oauth-login',
'fetch-login-code',
'post-login-phone-verification',
'bind-email',
'fetch-bind-email-code',
'confirm-oauth',
'platform-verify',
]);
@@ -12243,7 +12249,6 @@ const step8Executor = self.MultiPageBackgroundStep8?.createStep8Executor({
resolveSignupMethod,
reuseOrCreateTab,
sendToContentScriptResilient,
buildRegistrationEmailStateUpdates,
setState,
shouldUseCustomRegistrationEmail,
sleepWithStop,
@@ -12376,6 +12381,9 @@ const stepExecutorsByKey = {
'plus-checkout-return': (state) => plusReturnConfirmExecutor.executePlusReturnConfirm(state),
'oauth-login': (state) => step7Executor.executeStep7(state),
'fetch-login-code': (state) => step8Executor.executeStep8(state),
'post-login-phone-verification': (state) => step8Executor.executePostLoginPhoneVerification(state),
'bind-email': (state) => step8Executor.executeBindEmail(state),
'fetch-bind-email-code': (state) => step8Executor.executeFetchBindEmailCode(state),
'confirm-oauth': (state) => step9Executor.executeStep9(state),
'platform-verify': (state) => executeStep10(state),
};
@@ -13610,22 +13618,12 @@ async function waitForStep8Ready(tabId, timeoutMs = STEP8_READY_WAIT_TIMEOUT_MS,
throw new Error(`${CLOUDFLARE_SECURITY_BLOCK_ERROR_PREFIX}${CLOUDFLARE_SECURITY_BLOCK_USER_MESSAGE}`);
}
if (pageState?.addPhonePage || pageState?.phoneVerificationPage) {
const latestState = await getState();
if (!Boolean(latestState?.phoneVerificationEnabled)) {
const urlPart = pageState?.url ? ` URL: ${pageState.url}` : '';
throw new Error(
pageState?.phoneVerificationPage
? `步骤 ${visibleStep}:当前认证页进入手机验证码页,但未开启接码功能,无法继续自动授权。${urlPart}`.trim()
: `步骤 ${visibleStep}:当前认证页进入手机号页面,但未开启接码功能,无法继续自动授权。${urlPart}`.trim()
);
}
await phoneVerificationHelpers.completePhoneVerificationFlow(tabId, pageState, { visibleStep });
recovered = false;
await sleepWithStop(250);
continue;
}
if (pageState?.addPhonePage) {
throw new Error(`步骤 ${visibleStep}:认证页进入了手机号页面,当前不是 OAuth 同意页,无法继续自动授权。`);
const urlPart = pageState?.url ? ` URL: ${pageState.url}` : '';
throw new Error(
pageState?.phoneVerificationPage
? `步骤 ${visibleStep}:自动确认 OAuth 只处理 OAuth 授权页,当前仍在手机验证码页。${urlPart}`.trim()
: `步骤 ${visibleStep}:自动确认 OAuth 只处理 OAuth 授权页,当前仍在添加手机号页。${urlPart}`.trim()
);
}
if (pageState?.retryPage) {
const retryUrl = String(pageState?.url || '').trim();
@@ -13913,7 +13911,8 @@ async function recoverOAuthLocalhostTimeout(details = {}) {
const authLoginStep = typeof getAuthChainStartStepId === 'function'
? getAuthChainStartStepId(state || {})
: FINAL_OAUTH_CHAIN_START_STEP;
const loginCodeStep = Number(visibleStep) >= 12 ? 11 : 8;
const authLoginNodeId = String(getNodeIdByStepForState(authLoginStep, state || {}) || 'oauth-login').trim();
const confirmNodeId = String(getNodeIdByStepForState(visibleStep, state || {}) || 'confirm-oauth').trim();
await addLog(
`检测到 OAuth localhost 回调等待窗口已过期,正在复核认证页并回到步骤 ${authLoginStep} 重拉授权链路。`,
@@ -13932,7 +13931,7 @@ async function recoverOAuthLocalhostTimeout(details = {}) {
});
} catch (inspectError) {
await addLog(
`复核认证页状态失败(${getErrorMessage(inspectError)}),将先尝试按步骤 ${loginCodeStep} 收尾恢复`,
`复核认证页状态失败(${getErrorMessage(inspectError)}),将按当前 OAuth 流程图重新执行授权前置节点`,
'warn',
{ step: visibleStep, stepKey: 'confirm-oauth' }
);
@@ -13958,22 +13957,45 @@ async function recoverOAuthLocalhostTimeout(details = {}) {
if (!step7Executor?.executeStep7 || !step8Executor?.executeStep8) {
return null;
}
const workflowNodeIds = getAutoRunWorkflowNodeIds(latestState);
const authStartIndex = workflowNodeIds.indexOf(authLoginNodeId);
const confirmIndex = workflowNodeIds.indexOf(confirmNodeId);
if (authStartIndex < 0 || confirmIndex < 0 || authStartIndex >= confirmIndex) {
return null;
}
const recoveryNodeIds = workflowNodeIds.slice(authStartIndex, confirmIndex);
const runRecoveryNode = async (nodeId) => {
const recoveryState = await getState();
const recoveryStep = getStepIdByNodeIdForState(nodeId, recoveryState);
const payload = {
...recoveryState,
visibleStep: recoveryStep,
nodeId,
};
switch (nodeId) {
case 'oauth-login':
return step7Executor.executeStep7(payload);
case 'fetch-login-code':
return step8Executor.executeStep8(payload);
case 'post-login-phone-verification':
return step8Executor.executePostLoginPhoneVerification(payload);
case 'bind-email':
return step8Executor.executeBindEmail(payload);
case 'fetch-bind-email-code':
return step8Executor.executeFetchBindEmailCode(payload);
default:
throw new Error(`OAuth localhost 恢复不支持节点 ${nodeId}`);
}
};
await addLog(
`正在自动重开步骤 ${authLoginStep} -> ${loginCodeStep},恢复到可继续捕获 localhost 回调的状态`,
`正在自动重开 OAuth 前置节点:${recoveryNodeIds.join(' -> ')}`,
'warn',
{ step: visibleStep, stepKey: 'confirm-oauth' }
);
await step7Executor.executeStep7({
...latestState,
visibleStep: authLoginStep,
});
const stateAfterStep7 = await getState();
await step8Executor.executeStep8({
...stateAfterStep7,
visibleStep: loginCodeStep,
});
for (const nodeId of recoveryNodeIds) {
await runRecoveryNode(nodeId);
}
const recoveredState = await getState();
const oauthUrl = String(recoveredState?.oauthUrl || state?.oauthUrl || '').trim();
@@ -13989,7 +14011,7 @@ async function recoverOAuthLocalhostTimeout(details = {}) {
});
await addLog(
`已恢复到步骤 ${authLoginStep} -> ${loginCodeStep} 收尾状态,并刷新 OAuth localhost 回调等待窗口,准备重试当前步骤。`,
`已恢复到自动确认 OAuth 前置状态,并刷新 OAuth localhost 回调等待窗口,准备重试当前步骤。`,
'warn',
{ step: visibleStep, stepKey: 'confirm-oauth' }
);