feat(interrupt): force password login after about-you cutoff

This commit is contained in:
cong
2026-04-04 02:04:32 +08:00
parent b3a555004f
commit 4b81f2b0fc
2 changed files with 35 additions and 4 deletions

View File

@@ -252,6 +252,10 @@ class OAuthClient:
def _state_is_login_password(self, state: FlowState):
return state.page_type == "login_password"
def _state_is_create_account_password(self, state: FlowState):
target = f"{state.continue_url} {state.current_url}".lower()
return state.page_type == "create_account_password" or "create-account/password" in target
def _state_is_email_otp(self, state: FlowState):
target = f"{state.continue_url} {state.current_url}".lower()
return (
@@ -835,6 +839,7 @@ class OAuthClient:
prefer_passwordless_login=False,
allow_phone_verification=True,
force_new_browser=False,
force_password_login=False,
screen_hint="login",
complete_about_you_if_needed=False,
first_name="",
@@ -856,6 +861,7 @@ class OAuthClient:
skymail_client: Skymail 客户端(用于获取 OTP如果需要
prefer_passwordless_login: 是否强制走 passwordless OTP 链路
allow_phone_verification: add_phone 后是否允许进入手机号验证码分支
force_password_login: 即使 prefer_passwordless_login=true也强制走密码登录
complete_about_you_if_needed: 命中 about_you 后是否自动提交资料完成注册
screen_hint: authorize/continue 的 screen_hintlogin/signup
first_name: about_you 名字
@@ -879,6 +885,7 @@ class OAuthClient:
f"allow_phone_verification={'on' if allow_phone_verification else 'off'}, "
f"complete_about_you_if_needed={'on' if complete_about_you_if_needed else 'off'}, "
f"force_new_browser={'on' if force_new_browser else 'off'}, "
f"force_password_login={'on' if force_password_login else 'off'}, "
f"screen_hint={screen_hint or 'login'}"
)
@@ -968,7 +975,7 @@ class OAuthClient:
self._log("换取 tokens 失败")
return tokens
if prefer_passwordless_login and self._state_is_login_password(state):
if prefer_passwordless_login and (not force_password_login) and self._state_is_login_password(state):
next_state = self._send_passwordless_login_otp(
email,
device_id,
@@ -985,6 +992,24 @@ class OAuthClient:
state = next_state
continue
if self._state_is_create_account_password(state) and force_password_login:
self._log("命中 create_account_password按强制密码登录路径继续")
next_state = self._submit_password_verify(
password,
device_id,
user_agent=user_agent,
sec_ch_ua=sec_ch_ua,
impersonate=impersonate,
referer=state.current_url or state.continue_url or f"{self.oauth_issuer}/log-in/password",
)
if not next_state:
if not self.last_error:
self._set_error("密码验证后未进入下一步 OAuth 状态")
return None
referer = state.current_url or referer
state = next_state
continue
if self._state_is_login_password(state):
next_state = self._submit_password_verify(
password,

View File

@@ -445,9 +445,14 @@ class RefreshTokenRegistrationEngine:
self._log("3. 新开 OAuth session按 screen_hint=login + passwordless OTP 登录...")
self._log("4. 若命中 about_you则在 OAuth 会话内提交姓名+生日,再继续 workspace/token")
oauth_screen_hint = "login"
oauth_force_password_login = False
if registration_message == "pending_about_you_submission":
oauth_screen_hint = "signup"
self._log("OAuth 使用 screen_hint=signup 以恢复未完成的 about_you")
oauth_screen_hint = "login"
oauth_force_password_login = True
self._log(
"OAuth 使用 screen_hint=login + force_password_login "
"以完成密码登录 → OTP → about_you"
)
tokens = oauth_client.login_and_get_tokens(
result.email,
@@ -457,10 +462,11 @@ class RefreshTokenRegistrationEngine:
sec_ch_ua=getattr(register_client, "sec_ch_ua", None),
impersonate=getattr(register_client, "impersonate", None),
skymail_client=email_adapter,
prefer_passwordless_login=True,
prefer_passwordless_login=not oauth_force_password_login,
allow_phone_verification=False,
force_new_browser=True,
screen_hint=oauth_screen_hint,
force_password_login=oauth_force_password_login,
complete_about_you_if_needed=True,
first_name=first_name,
last_name=last_name,