@@ -1085,7 +1085,7 @@ test.describe('severity-2', () => {
10851085 test . describe ( 'Passwordless authentication - Browser Service (Relay)' , ( ) => {
10861086 test ( 'passwordless signin via Relay OAuth flow' , async ( {
10871087 target,
1088- pages : { page, signin, signinPasswordlessCode } ,
1088+ syncOAuthBrowserPages : { page, signin, signinPasswordlessCode } ,
10891089 testAccountTracker,
10901090 } ) => {
10911091 const { email } = await testAccountTracker . signUpPasswordless ( ) ;
@@ -1109,7 +1109,7 @@ test.describe('severity-2', () => {
11091109
11101110 test ( 'passwordless signup via Relay OAuth flow - service allowed' , async ( {
11111111 target,
1112- pages : { page, signin, signinPasswordlessCode } ,
1112+ syncOAuthBrowserPages : { page, signin, signinPasswordlessCode } ,
11131113 testAccountTracker,
11141114 } , { project } ) => {
11151115 test . skip (
@@ -1137,6 +1137,89 @@ test.describe('severity-2', () => {
11371137 await expect ( page ) . not . toHaveURL ( / s i g n i n _ p a s s w o r d l e s s _ c o d e / ) ;
11381138 } ) ;
11391139
1140+ test ( 'passwordless signin via Relay OAuth flow - account with 2FA proceeds to TOTP verification' , async ( {
1141+ target,
1142+ syncOAuthBrowserPages : { page, signin, signinPasswordlessCode, signinTotpCode } ,
1143+ testAccountTracker,
1144+ } ) => {
1145+ // Create passwordless account and set up TOTP via API
1146+ const { email, sessionToken } =
1147+ await testAccountTracker . signUpPasswordless ( ) ;
1148+ const account : any = testAccountTracker . accounts . find (
1149+ ( a ) => a . email === email
1150+ ) ;
1151+ if ( ! account ) {
1152+ throw new Error (
1153+ `Account for email ${ email } not found in testAccountTracker.accounts`
1154+ ) ;
1155+ }
1156+ const password = account . password ;
1157+
1158+ const { secret } = await target . authClient . createTotpToken (
1159+ sessionToken ,
1160+ { }
1161+ ) ;
1162+ const totpCode = await getTotpCode ( secret ) ;
1163+ await target . authClient . verifyTotpSetupCode ( sessionToken , totpCode ) ;
1164+ await target . authClient . completeTotpSetup ( sessionToken ) ;
1165+
1166+ if ( account ) {
1167+ account . secret = secret ;
1168+ account . sessionToken = sessionToken ;
1169+ }
1170+
1171+ await signin . clearCache ( ) ;
1172+
1173+ // Sign in via Relay OAuth flow
1174+ const params = new URLSearchParams ( relayDesktopOAuthQueryParams ) ;
1175+ params . set ( 'force_passwordless' , 'true' ) ;
1176+ await signin . goto ( '/authorization' , params ) ;
1177+
1178+ await signin . fillOutEmailFirstForm ( email ) ;
1179+
1180+ // Should redirect to passwordless code page
1181+ await page . waitForURL ( / s i g n i n _ p a s s w o r d l e s s _ c o d e / ) ;
1182+
1183+ const passwordlessCode =
1184+ await target . emailClient . getPasswordlessSigninCode ( email ) ;
1185+ await signinPasswordlessCode . fillOutCodeForm ( passwordlessCode ) ;
1186+
1187+ // Should redirect to TOTP code entry page
1188+ await page . waitForURL ( / s i g n i n _ t o t p _ c o d e / ) ;
1189+
1190+ const newTotpCode = await getTotpCode ( secret ) ;
1191+ await signinTotpCode . fillOutCodeForm ( newTotpCode ) ;
1192+
1193+ // Should complete OAuth flow and land on settings
1194+ await page . waitForURL ( / \/ s e t t i n g s / ) ;
1195+
1196+ // Cleanup: set password so testAccountTracker can destroy the account
1197+ await target . authClient . passwordlessSendCode ( email , {
1198+ clientId : 'dcdb5ae7add825d2' ,
1199+ } ) ;
1200+ const cleanupCode =
1201+ await target . emailClient . getPasswordlessSigninCode ( email ) ;
1202+ const cleanupResult = await target . authClient . passwordlessConfirmCode (
1203+ email ,
1204+ cleanupCode ,
1205+ { clientId : 'dcdb5ae7add825d2' }
1206+ ) ;
1207+ const cleanupTotpCode = await getTotpCode ( secret ) ;
1208+ await target . authClient . verifyTotpCode (
1209+ cleanupResult . sessionToken ,
1210+ cleanupTotpCode
1211+ ) ;
1212+ await target . authClient . createPassword (
1213+ cleanupResult . sessionToken ,
1214+ email ,
1215+ password
1216+ ) ;
1217+
1218+ if ( account ) {
1219+ account . isPasswordless = false ;
1220+ }
1221+ } ) ;
1222+
11401223 test ( 'passwordless signup blocked for service not in allowedClientServices' , async ( {
11411224 target,
11421225 pages : { page, signin } ,
0 commit comments