iOS 第三方登入後回不到原頁?分頁開啟關係與回頁行為實測
記錄 iOS Safari 與 Chrome 在多分頁第三方登入流程中,登入頁關閉後不一定回到原頁的實測,以及分頁開啟關係、window.close 與 window.focus 的限制。
W
在處理 iOS 第三方 Google 登入時,除了登入本身之外,還遇到另一個很特別的問題:
Google 登入成功、登入分頁也關掉了,但為什麼沒有回到原本的頁面?
一開始以為登入流程應該很單純:
原頁面
↓
開啟 Google 登入分頁
↓
登入完成
↓
關閉 Google 分頁
↓
回到原頁面
但實際在 iOS Safari 與 Chrome 測試後,發現「登入頁關閉後會回到哪個分頁」,和原本頁面曾經開過哪些分頁有關。
兩種情況的差異
假設:
A:原本頁面
B:其他分頁
C:Google 登入分頁
情況一:B 是由 A 開出去的
例如使用者先在 A 點擊某個連結,開出 B:
A
↓
A 開啟 B
↓
使用者再切回 A
↓
A 開啟 Google 登入 C
↓
Google 登入完成
↓
C 關閉
原本預期:
C 關閉
↓
回到 A
但實測可能變成:
C 關閉
↓
顯示 B
也就是:
即使 Google 登入是從 A 開始,登入頁關閉後也可能顯示先前由 A 開出去的 B。
情況二:B 不是由 A 開出去的
如果 B 是使用者自己另外開啟的分頁,和 A 沒有直接的開啟關係:
使用者自己開 B
↓
切回 A
↓
A 開啟 Google 登入 C
↓
Google 登入完成
↓
C 關閉
這種情況實測反而比較能正常回到:
A
簡單比較
| 情況 | 分頁關係 | Google 登入完成後 |
|---|---|---|
| A 曾經開出 B | A → B,再由 A → C | C 關閉後可能顯示 B |
| B 是使用者自己開的 | B 與 A 沒有直接開啟關係,再由 A → C | C 關閉後較能回到 A |
這也是當時最容易讓人困惑的地方。
表面上兩種情況看起來都是:
人在 A
↓
開 Google 登入
↓
登入成功
但因為前面分頁的建立方式不同,最後關閉登入頁後的結果也可能不同。
Safari 與 Chrome 的表現也不完全一樣
測試過程中也觀察到 Safari 與 Chrome 在 iOS 上的新分頁排列方式並不完全相同。
例如當時測試時:
- Safari 比較容易把新開的相關分頁放在原分頁附近
- Chrome 的新分頁位置可能不同
因此最後登入頁關閉時,瀏覽器選擇顯示哪一個分頁,也可能有所差異。
不過這比較適合作為實測紀錄,而不是固定規格,因為瀏覽器版本更新後行為仍可能改變。
iframe 也不能控制所有分頁
當 Web 應用是執行在 iframe 中時,還會多一層限制。
如果登入頁是自己的程式透過:
const loginWindow = window.open(loginUrl);
開出去,而且仍保有這個 Window reference,通常比較容易控制:
loginWindow?.close();
但如果某個分頁是宿主頁面、其他流程或瀏覽器本身產生的,iframe 並不會自動取得它的控制權。
所以比較簡單的理解方式是:
自己開出去、而且還掌握 reference 的分頁比較容易控制;其他分頁不要假設自己可以直接關閉。
window.focus() 也不能保證切回原頁
即使登入成功後呼叫:
window.opener?.focus();
也不能保證瀏覽器一定會把使用者切回指定分頁。
因此:
Google 登入成功
↓
window.close()
↓
window.focus()
↓
一定回到原頁
這個流程不能當成可靠前提。
最後的心得
這次測試後,我覺得最重要的不是去猜:
「Safari 到底會回哪一頁?」
而是不要讓登入流程依賴這件事情。
比較安全的設計是:
Google 登入成功
↓
保存登入結果
↓
登入分頁關閉
接下來不論:
直接回到原頁
或:
瀏覽器先顯示其他分頁
↓
使用者之後自己回到原頁
都應該能繼續使用已完成的登入狀態。
簡單來說:
瀏覽器決定使用者最後看到哪個分頁;系統則要負責確保登入狀態不會因此遺失。