fix: preserve Teams return URL during auth login - skip goto when already on login page, poll for redirect completion

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ValueOn AG 2026-02-16 14:01:52 +01:00
parent 325de1c9ae
commit 4b6adaad8d
2 changed files with 59 additions and 24 deletions

View file

@ -36,11 +36,21 @@ export class AuthProcedure {
try { try {
this._logger.info(`Authenticating as ${email}...`); this._logger.info(`Authenticating as ${email}...`);
// Navigate to Microsoft login // Only navigate to login page if not already there.
await this._page.goto(_LOGIN_URL, { // When called after clicking "Sign in" on Teams pre-join page,
waitUntil: 'domcontentloaded', // the browser is already on login.microsoftonline.com WITH a return URL
timeout: 30000, // embedded by Teams. Navigating again would destroy that return URL!
}); const currentUrl = this._page.url();
if (!currentUrl.includes('login.microsoftonline.com')) {
this._logger.info('Not on login page yet, navigating to Microsoft login...');
await this._page.goto(_LOGIN_URL, {
waitUntil: 'domcontentloaded',
timeout: 30000,
});
} else {
this._logger.info('Already on Microsoft login page - skipping navigation to preserve return URL');
await this._page.waitForLoadState('domcontentloaded', { timeout: 15000 });
}
// Wait for email input // Wait for email input
const emailInput = await this._page.waitForSelector( const emailInput = await this._page.waitForSelector(

View file

@ -214,32 +214,57 @@ export class BotOrchestrator {
if (authSuccess) { if (authSuccess) {
this._logger.info('Authentication via "Sign in" link succeeded'); this._logger.info('Authentication via "Sign in" link succeeded');
// After login, Teams does a redirect chain automatically: // After login, the redirect chain goes automatically:
// Login → M365 → Teams v2 → Pre-Join page (/v2/) // login.microsoftonline.com → teams.microsoft.com/v2/?meetingjoin=true#/meet/...
// Do NOT navigate anywhere. Just wait for the redirect chain to complete // The return URL is embedded by Teams when clicking "Sign in".
// and for the "Join now" button to appear on the Teams v2 pre-join page. // We just wait for the redirect to complete.
this._logger.info('Waiting for Teams to redirect to authenticated pre-join page...'); this._logger.info('Waiting for redirect chain to leave login.microsoftonline.com...');
// Wait for the #prejoin-join-button to appear (up to 30 seconds) // Step 1: Wait for URL to leave login.microsoftonline.com (poll up to 45s)
// This button only exists on the Teams v2 authenticated pre-join page const maxWaitMs = 45000;
const pollIntervalMs = 1000;
const startTime = Date.now();
let leftLoginPage = false;
while (Date.now() - startTime < maxWaitMs) {
const currentUrl = this._page!.url();
if (!currentUrl.includes('login.microsoftonline.com')) {
this._logger.info(`Left login page after ${Date.now() - startTime}ms. URL: ${currentUrl.substring(0, 100)}`);
leftLoginPage = true;
break;
}
await this._page!.waitForTimeout(pollIntervalMs);
}
if (!leftLoginPage) {
const stuckUrl = this._page!.url();
this._logger.warn(`Still on login page after ${maxWaitMs}ms. URL: ${stuckUrl.substring(0, 100)}`);
// Try navigating to meeting URL as fallback (auth cookies should be set)
this._logger.info('Fallback: navigating to meeting URL with auth cookies...');
await this._page!.goto(this._meetingUrl, { waitUntil: 'domcontentloaded', timeout: 30000 });
await this._joinProcedure!.handleLauncherIfPresent();
}
// Step 2: Wait for the pre-join page to fully load
// The #prejoin-join-button appears on the Teams v2 authenticated pre-join page
const joinButtonSelector = '#prejoin-join-button, button[data-tid="prejoin-join-button"]'; const joinButtonSelector = '#prejoin-join-button, button[data-tid="prejoin-join-button"]';
try { try {
await this._page!.waitForSelector(joinButtonSelector, { timeout: 30000, state: 'visible' }); await this._page!.waitForSelector(joinButtonSelector, { timeout: 30000, state: 'visible' });
const currentUrl = this._page!.url(); const finalUrl = this._page!.url();
this._logger.info(`Arrived at authenticated pre-join page: ${currentUrl.substring(0, 80)}`); this._logger.info(`On authenticated pre-join page: ${finalUrl.substring(0, 100)}`);
} catch { } catch {
const currentUrl = this._page!.url(); const finalUrl = this._page!.url();
const pageContent = await this._page!.evaluate(() => document.body?.innerText?.substring(0, 300) || ''); const pageContent = await this._page!.evaluate(() => document.body?.innerText?.substring(0, 300) || '');
this._logger.warn(`Join button not found after auth redirect. URL: ${currentUrl.substring(0, 80)}`); this._logger.warn(`Join button not found. URL: ${finalUrl.substring(0, 100)}`);
this._logger.warn(`Page content: ${pageContent.substring(0, 200)}`); this._logger.warn(`Page content: ${pageContent.substring(0, 200)}`);
}
// If we ended up somewhere unexpected, try meeting URL as last resort
// Verify we're on the authenticated pre-join page if (!finalUrl.includes('teams.microsoft.com')) {
const pageText = await this._page!.evaluate(() => document.body?.innerText?.substring(0, 500) || ''); this._logger.info('Not on Teams - navigating to meeting URL as last resort...');
if (pageText.includes('Join now')) { await this._page!.goto(this._meetingUrl, { waitUntil: 'domcontentloaded', timeout: 30000 });
this._logger.info('On authenticated pre-join page with "Join now" button'); await this._joinProcedure!.handleLauncherIfPresent();
} else { await this._page!.waitForTimeout(5000);
this._logger.warn(`Post-auth page content: ${pageText.substring(0, 300)}`); }
} }
} else { } else {
this._logger.warn('Authentication via "Sign in" failed - continuing as anonymous'); this._logger.warn('Authentication via "Sign in" failed - continuing as anonymous');