demo · v131
OAuth popup flow under each COOP value
An OAuth implicit-flow popup needs to (a) open from a click and (b) ship a token back to the opener. Some COOP values block (b). This page lays out three flows side-by-side: default unsafe-none, the new noopener-allow-popups, and full same-origin. Each tile shows what works.
1. opener: unsafe-none (default)
Cross-Origin-Opener-Policy: unsafe-none
Bidirectional access — the popup can script the opener and vice versa. Vulnerable to cross-origin Spectre-style leaks.
2. opener: noopener-allow-popups (new in v131)
Cross-Origin-Opener-Policy: noopener-allow-popups
The new sweet spot: popup still opens, but it's noopener by default. Use BroadcastChannel or a redirect-back to deliver the token instead of window.opener.postMessage.
3. opener: same-origin
Cross-Origin-Opener-Policy: same-origin
Maximum isolation. Cross-origin popups (most OAuth providers) lose the opener relationship entirely, breaking many flows.
live opener check
no popups yetmigration recipe
If you have an OAuth implicit-flow popup, swap window.opener.postMessage for a BroadcastChannel or for a redirect that posts the token back through a fetch. Then deploy the new COOP value to neutralise the attack surface without breaking the flow.
// Old (works under unsafe-none, broken under noopener-allow-popups):
window.opener.postMessage({ token }, "*");
// New (works everywhere):
const bc = new BroadcastChannel("auth");
bc.postMessage({ token });
bc.close();