<?xml version="1.0" encoding="utf-8"?>
<!-- name="GENERATOR" content="github.com/mmarkdown/mmark Mmark Markdown Processor - mmark.miek.nl" -->
<rfc version="3" ipr="trust200902" docName="draft-meyerzuselha-oauth-web-message-response-mode-01" submissionType="IETF" category="std" xml:lang="en" xmlns:xi="http://www.w3.org/2001/XInclude" indexInclude="true" consensus="true">

<front>
<title abbrev="oauth-web-message-response-mode">OAuth 2.0 Web Message Response Mode for Popup- and Iframe-based Authorization Flows</title><seriesInfo value="draft-meyerzuselha-oauth-web-message-response-mode-01" stream="IETF" status="standard" name="Internet-Draft"></seriesInfo>
<author initials="K." surname="Meyer zu Selhausen" fullname="Karsten Meyer zu Selhausen"><organization>Hackmanit</organization><address><postal><street></street>
</postal><email>karsten.meyerzuselhausen@hackmanit.de</email>
</address></author><author initials="L." surname="Jannett" fullname="Louis Jannett"><organization>Ruhr University Bochum</organization><address><postal><street></street>
</postal><email>louis.jannett@rub.de</email>
</address></author><author initials="C." surname="Mainka" fullname="Christian Mainka"><organization>Hackmanit</organization><address><postal><street></street>
</postal><email>christian.mainka@hackmanit.de</email>
</address></author><date/>
<area>Security</area>
<workgroup>Web Authorization Protocol</workgroup>
<keyword>security</keyword>
<keyword>oauth2</keyword>

<abstract>
<t>This specification defines the web message response mode that authorization servers use for transmitting authorization response parameters via the user-agent's postMessage API to the client.
This mode is intended for authorization flows that use secondary windows, which are well-suited for browser-based applications.</t>
</abstract>

</front>

<middle>

<section anchor="Introduction"><name>Introduction</name>
<t>OAuth <xref target="RFC6749"></xref> uses HTTP redirects to transfer authorization response parameters from the authorization server via the user-agent to the client's redirection endpoint.
In this case, the authorization response parameters are encoded in the query string (<tt>response_mode=query</tt>) or in the fragment (<tt>response_mode=fragment</tt>) of the <tt>redirect_uri</tt> <xref target="oauth.encoding" sectionFormat="parens" relative="#" section="2.1"></xref>.
<xref target="RFC6749" sectionFormat="parens" relative="#" section="1.7"></xref> allows other mechanisms available via the user-agent to accomplish this redirection, such as <tt>response_mode=form_post</tt> <xref target="oauth.post"></xref>.</t>
<t>The standardized query, fragment, and form post response modes are designed for single-window authorization but not for multi-window authorization flows.
A common example is a popup-based authorization flow, where the client's primary window opens the authorization server in a secondary window.
The secondary window cannot use HTTP redirects to transfer response parameters back to the client in the primary window.</t>
<t>This specification defines the web message response mode that uses the user-agent's postMessage API <xref target="whatwg.postmessage"></xref> to exchange messages between two different browser windows.
Clients inform the authorization server to use this response mode for returning the authorization response by setting the <tt>response_mode</tt> parameter in the authorization request to <tt>web_message</tt>.
This response mode facilitates popup-based and iframe-based authorization flows, in which the authorization server is called in a secondary window or embedded in a frame on the client.</t>
<t>These flows that span the authorization process across two windows are especially useful for browser-based applications, where the main application window should remain uninterrupted to preserve the user experience.
Executing authorization flows in invisible iframes can also enable seamless session resumption and renewal without disrupting the user.</t>

<section anchor="conventions-and-terminology"><name>Conventions and Terminology</name>
<t>The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in BCP 14 <xref target="RFC2119"></xref> <xref target="RFC8174"></xref> when, and only when, they appear in all capitals, as shown here.</t>
<t>This specification uses the terms &quot;client&quot;, &quot;user-agent&quot;, &quot;authorization server&quot;, &quot;authorization endpoint&quot;, &quot;redirection endpoint&quot;, &quot;redirection URI&quot;, &quot;authorization request&quot;, and &quot;authorization response&quot; defined by the OAuth 2.0 Authorization Framework <xref target="RFC6749"></xref>.
It further uses the term &quot;response mode&quot; defined by the OAuth 2.0 Multiple Response Type Encoding Practices <xref target="oauth.encoding"></xref>.</t>
<t>This specification defines the following additional terminology.</t>

<dl spacing="compact">
<dt>primary window</dt>
<dd>This is the top-level browsing window that initially holds the client's website.
This window has no parent windows and it was not opened by any other window.</dd>
<dt>secondary window</dt>
<dd>This is the window in which the client in the primary window opens the authorization server.</dd>
</dl>
</section>
</section>

<section anchor="WebMessageResponseMode"><name>Web Message Response Mode</name>
<t>This specification defines the web message response mode, which is described with the following <tt>response_mode</tt> parameter value in the authorization request <xref target="oauth.encoding"></xref>.</t>

<dl spacing="compact">
<dt><tt>web_message</tt></dt>
<dd>In the web message response mode, the authorization server in the secondary window encodes the authorization response parameters in a JSON dictionary and transmits it via the user-agent's postMessage API to the client in the primary window.</dd>
</dl>
<t>If the authorization request includes the value <tt>web_message</tt> for the <tt>response_mode</tt> parameter, the authorization server:</t>

<ul spacing="compact">
<li>MUST dynamically discover the client's primary window reference as described in <xref target="DynamicDiscover"></xref>.</li>
<li>MUST use the user-agent's postMessage API to return the authorization response to the client's primary window.</li>
<li>MUST encode the response paramters as key-value string pairs in a JSON dictionary.</li>
<li>MUST follow <xref target="RFC6749"></xref> and <xref target="RFC9700"></xref> when validating the redirection URI.</li>
<li>MUST use the full redirection URI (the exact same URI also used in other response modes such as query, fragment, or form post) as the postMessage's receiver origin.
The user-agent's postMessage API inherently parses the redirection URI and extracts its origin.</li>
<li>MUST NOT parse the URI itself to reduce the attack surface concerning parsing issues.</li>
</ul>
<t>The client's redirection URI MUST serve as the postMessage's receiver origin to protect the authorization response from being leaked to malicious origins.</t>
<t>This example illustrates how an authorization server (identified by the issuer <tt>https://as.example</tt>) in a secondary window returns the authorization response to the client (whose registered redirection URI is <tt>https://client.example/cb</tt>) in the primary window using the postMessage API:</t>

<sourcecode type="js">const primaryWindowRef = window.opener // for popup-based flow
const primaryWindowRef = window.parent // for iframe-based flow
const params = {
  &quot;code&quot;: &quot;XXXXXXXX&quot;,
  &quot;state&quot;:&quot;XXXXXXXX&quot;,
  &quot;iss&quot;: &quot;https://as.example&quot;
}
primaryWindowRef.postMessage(params, &quot;https://client.example/cb&quot;)
</sourcecode>
<t>The client MAY signal its preferred primary window reference by using the <tt>response_mode</tt> parameter.
For popup-based authorization flows, it MAY set the value to <tt>web_message.opener</tt>, and for iframe-based authorization flows, it MAY set the value to <tt>web_message.parent</tt>.
When either <tt>web_message.opener</tt> or <tt>web_message.parent</tt> is specified, the authorization server MUST use the corresponding window reference <tt>window.opener</tt> or <tt>window.parent</tt> and MUST NOT attempt to dynamically determine the primary window reference as specified in <xref target="DynamicDiscover"></xref>.</t>

<section anchor="DynamicDiscover"><name>Dynamic Discovery of Primary Window Reference</name>
<t>If the authorization request specifies <tt>web_message</tt> as the <tt>response_mode</tt>, the authorization server running in the secondary window MUST dynamically determine the client's primary window reference.
This is done by checking whether the <tt>window.opener</tt> or <tt>window.parent</tt> references point to a valid primary window.
If both references are available, the <tt>window.opener</tt> reference MUST take precedence to ensure that popup-based authorization flows are prioritized over iframe-based flows.</t>
<t>The following example illustrates how an authorization server may perform this discovery process:</t>

<sourcecode type="js">let primaryWindowRef = undefined
if (window.opener !== null) // this is a popup-based flow
  primaryWindowRef = window.opener
else if (window.parent !== self) // this is an iframe-based flow
  primaryWindowRef = window.parent
else // abort flow: could not discover primary window reference
</sourcecode>
</section>
</section>

<section anchor="PopupMode"><name>Popup-Based Authorization Flow Using the Web Message Response Mode</name>
<t>In a popup-based authorization flow, the client opens the authorization endpoint in a secondary window.
The authorization server uses the user-agent's postMessage API to return the authorization response parameters from the secondary window back to the client running in the primary window.
The flow is depicted in <xref target="PopupFlow"></xref> and described in the following.</t>
<figure anchor="PopupFlow"><name>Overview of a popup-based authorization flow using the web message response mode. </name>
<sourcecode type="ascii-art">+------------------------------+
|        Primary Window        |
|    (client.example/login)    |    +-----------------------+
|                              |    |   Secondary Window    |
|1) Register message event     |    |  (as.example/authz)   |
|   handler                    |    |                       |
|                              |    |3) Authenticate user   |
|2) Open authz request with    |    |   and authorize       |
|   web message response mode  |    |   access              |
|   parameter in popup window  +---&gt;|                       |
|                              |    |4) Send postMessage    |
|5) Validate and process authz |&lt;---+   with authz response |
|   response in event handler  |    |   to opener window    |
|                              |    |                       |
+------------------------------+    +-----------------------+
</sourcecode>
</figure>

<ol spacing="compact">
<li>The client registers a message event handler that receives the authorization response from the authorization server.
The client MUST validate the message's origin with an exact string matching the authorization server's origin.
As the authorization response is meant for one-time use, the client MUST remove the message event handler after receiving the authorization response to prevent any further authorization attempts.</li>
</ol>
<t>Example of the registration of a message event handler:</t>

<sourcecode type="js">const callback = (e) =&gt; {
  if (e.origin === &quot;https://as.example&quot;) {
    // further validation and processing of the authorization response
    process(e.data)
    window.removeEventListener(&quot;message&quot;, callback)
  }
}
window.addEventListener(&quot;message&quot;, callback)
</sourcecode>

<ol spacing="compact" start="2">
<li>The client MUST open the authorization request in a secondary window.
Therefore, the client
MAY use JavaScript and the user-agent's <tt>window.open</tt> API,
MAY use an anchor HTML element with a target attribute, or
MAY use any other mechanism suitable for opening secondary windows.
The authorization request MUST include the <tt>response_mode</tt> parameter value <tt>web_message</tt> or <tt>web_message.opener</tt>.
Additional authorization request parameters and techniques, such as PAR <xref target="RFC9126"></xref> and RAR <xref target="RFC9396"></xref>, are unaffected by this specification and MAY be used with the web message response mode.</li>
</ol>
<t>Example of using the <tt>window.open</tt> API to open the authorization request in a secondary window:</t>

<sourcecode type="js">window.open(
  &quot;https://as.example/auth?...&amp;response_mode=web_message&quot;,
  &quot;secondaryWindowRef&quot;,
  &quot;left=100,top=100,width=320,height=320&quot;
)
</sourcecode>
<t>Example of using an anchor tag with a target attribute to open the authorization request in a secondary window:</t>

<sourcecode type="html">&lt;a
  href=&quot;https://as.example/auth?...&amp;response_mode=web_message&quot;
  target=&quot;secondaryWindowRef&quot;
&gt;
</sourcecode>

<ol start="3">
<li><t>The authorization server receives the authorization request, validates its parameters, and proceeds with the end-user authentication and authorization, which is outside of the scope of this specification.</t>
</li>
<li><t>If the authorization request includes the <tt>response_mode</tt> parameter value <tt>web_message</tt> or <tt>web_message.opener</tt>, the authorization server MUST follow the web message response mode as described in <xref target="WebMessageResponseMode"></xref> and use the user-agent's postMessage API to return the authorization response parameters from the secondary window to the secondary window's opener window.
The receiver window MUST be referenced by the secondary window's <tt>opener</tt> property.</t>
</li>
</ol>
<t>Example of an authorization server using the postMessage API in a secondary window to return the authorization response to the client in the primary window:</t>

<sourcecode type="js">const params = {
  &quot;code&quot;: &quot;XXXXXXXX&quot;,
  &quot;state&quot;: &quot;XXXXXXXX&quot;,
  &quot;iss&quot;: &quot;https://as.example&quot;
}
window.opener.postMessage(params, &quot;https://client.example/cb&quot;)
</sourcecode>

<ol spacing="compact" start="5">
<li>The client's message event handler receives the postMessage that contains the authorization response parameters.
The further processing and validation of all parameters is out of the scope of this specification and MUST be compliant to <xref target="RFC6749"></xref> and <xref target="RFC9700"></xref>.</li>
</ol>
</section>

<section anchor="iframe-based-authorization-flow-using-the-web-message-response-mode"><name>Iframe-Based Authorization Flow Using the Web Message Response Mode</name>
<t>In addition to secondary windows being popups, iframes can be used as well.
Iframes enable a seamless authorization flow where the end-user only sees a single browser tab, without ever leaving the actual client.
The client MAY explicitly request the iframe-based authorization flow by setting the <tt>response_mode</tt> parameter to <tt>web_message.parent</tt>.
The authorization flow proceeds in a manner technically similar to the popup-based flow described in <xref target="PopupMode"></xref>, with the following modifications:</t>

<ul spacing="compact">
<li>In step 2, the client MUST embed the authorization request in an iframe instead of opening a popup window.</li>
<li>In step 4, the secondary window MUST reference its <tt>parent</tt> window rather than its <tt>opener</tt> window.</li>
</ul>
<t>If user consent has already been granted, iframe-based authorization flows can enable seamless session resumption or renewal by embedding invisible iframes with the <tt>prompt</tt> parameter set to <tt>none</tt> <xref target="openid.core" sectionFormat="parens" relative="#" section="3.1.2.1"></xref>.
In this case, the client receives the authorization response directly, allowing the user session to resume without further interaction.
If the <tt>prompt</tt> parameter is set to <tt>none</tt> but no prior user authentication or consent exists, the authorization server MUST return an error as specified in <xref target="openid.core" sectionFormat="parens" relative="#" section="3.1.2.1"></xref>.
In this case, the client can fall back to a popup-based flow or to an iframe-based flow that displays a Clickjacking-protected user interface, as discussed in <xref target="Clickjacking"></xref>.</t>

<section anchor="Clickjacking"><name>Clickjacking Mitigations in Iframes</name>
<t>The authorization server MUST implement Clickjacking countermeasures according to <xref target="RFC9700" sectionFormat="parens" relative="#" section="4.16"></xref> and protect its authorization endpoint and consent-page from being embedded in an iframe by origins not deemed trustworthy.</t>
<t>If the user's browser supports the Intersection Observer v2 API <xref target="w3c.observerv2"></xref>, the authorization server MAY use it to allow the client to embed the authorization endpoint and consent-page.
For example, the authorization server's script running in the embedded consent-page could pre-emptively load itself in a popup window if it detects the Intersection Observer v2 API's <tt>isVisible</tt> attribute being set to <tt>false</tt>, thus avoiding any occlusion of its content.</t>
</section>

<section anchor="user-session-in-iframes"><name>User-Session in Iframes</name>
<t>Modern browsers have started to disable the support for third-party cookies.
Thereby, iframes do not send authentication cookies along with requests in sub resource requests, such as iframes.
Using iframes as secondary windows therefore requires special exceptions to bypass this restriction, such as the Storage Access API <xref target="mozilla.storageaccessapi"></xref>.</t>
<t>This mechanism is unnecessary in first-party scenarios where the authorization server and client share the same origin.
In such cases, cookies are treated as first-party and remain included in requests made from iframes.</t>
</section>
</section>

<section anchor="authorization-server-metadata"><name>Authorization Server Metadata</name>
<t>Authorization servers MUST announce their support for the web message response mode defined in <xref target="WebMessageResponseMode"></xref> by adding <tt>web_message</tt>, <tt>web_message.opener</tt>, <tt>web_message.parent</tt>, or any combinations of these values to the <tt>response_modes_supported</tt> list in their authorization server metadata as specified in <xref target="RFC8414" sectionFormat="parens" relative="#" section="2"></xref>.
Authorization servers MAY declare exclusive support for a specific authorization flow by including either <tt>web_message.opener</tt> or <tt>web_message.parent</tt> in the <tt>response_modes_supported</tt> list.
If the <tt>response_modes_supported</tt> list contains the generic value <tt>web_message</tt>, the authorization server MUST support both the popup-based and the iframe-based authorization flows.</t>
</section>

<section anchor="Security"><name>Security Considerations</name>

<section anchor="receiver-origin-validation"><name>Receiver Origin Validation</name>
<t>Authorization servers MUST follow <xref target="WebMessageResponseMode"></xref> and <xref target="RFC9700" sectionFormat="parens" relative="#" section="4.17.2"></xref> when validating the postMessage receiver origin.
Otherwise, the authorization response may leak to an attacker, as described in <xref target="RFC9700" sectionFormat="parens" relative="#" section="4.17.1.1"></xref> and <xref target="RFC9700" sectionFormat="parens" relative="#" section="4.17.1.2"></xref>.</t>
</section>

<section anchor="initiator-origin-validation-and-cross-site-request-forgery-protection"><name>Initiator Origin Validation and Cross-Site Request Forgery Protection</name>
<t>In redirect-based authorization flows, there is no inherent mechanism available that enables a client to verify that the trusted authorization server initiates a redirection.
Instead, <xref target="RFC6749"></xref> introduces the <tt>state</tt> parameter to counter so-called Cross-Site Request Forgery (CSRF) attacks <xref target="RFC9700" sectionFormat="parens" relative="#" section="4.7"></xref> against the client's redirection endpoint by maintaining a state between the authorization request and response.</t>
<t>The postMessage API provides an inherent mechanism to verify the initiator of a postMessage.
The client MUST use this mechanism as described in <xref target="WebMessageResponseMode"></xref> and <xref target="RFC9700" sectionFormat="parens" relative="#" section="4.17.2"></xref> to verify that the trusted authorization server is the initiator of the postMessage.
Otherwise, an attacker can inject a maliciously crafted authorization response to the client <xref target="RFC9700" sectionFormat="parens" relative="#" section="4.17.1.3"></xref>.
This verification prevents some variants of CSRF attacks, where the attacker wants to log in a victim to the attacker's account.</t>
<t>However, attackers can also use CSRF attacks to log in a victim to the victim's own account.
This attack variant cannot be mitigated with the checks mentioned above.
Instead, a proper CSRF countermeasure, as described in <xref target="RFC9700" sectionFormat="parens" relative="#" section="4.7.1"></xref> MUST be used.</t>
</section>

<section anchor="data-validation"><name>Data Validation</name>
<t>Even after the initiator origin of the postMessage is validated, the client MUST check that the postMessage has the expected format <xref target="whatwg.postmessage" sectionFormat="parens" relative="#" section="9.3.2.1"></xref>.
In particular, the postMessage MUST NOT be processed in unsafe JavaScript sinks like <tt>eval</tt> or <tt>innerHTML</tt> to prevent cross-site scripting (XSS) flaws and other potentially malicious injections.
Otherwise, if the authorization server has been attacked using an XSS flaw, further unchecked processing of the postMessage could result in the attack being propagated into the client.</t>
</section>

<section anchor="cross-site-leak-protections-on-the-authorization-server"><name>Cross-Site Leak Protections on the Authorization Server</name>
<t>The authorization server is opened in a secondary window that needs access to its opener window via its <tt>opener</tt> property to send postMessages to that referenced window.
Thus, the authorization server cannot use cross-site leak protections like the cross-origin opener policy <xref target="whatwg.coop"></xref> to force the creation of a new top-level browsing context and cross-origin isolate their sites.</t>
<t>However, browsers are working on preventing cross-site leaks without breaking the popup-based authorization flows with the <tt>restrict-properties</tt> directive being added to the cross-origin opener policy <xref target="google.restrictprops"></xref>.
With this directive, properties that can be used for cross-site leaks are not available but postMessage communication between cross-origin windows is still allowed.
Authorization servers MAY set the <tt>Cross-Origin-Opener-Policy: restrict-properties</tt> header to protect against cross-site leaks.</t>
</section>

<section anchor="redirection-uri-vs-receiver-origin"><name>Redirection URI vs. Receiver Origin</name>
<t>In redirect-based authorization flows, the confidentiality of the authorization response is scoped to the redirection URI that contains a path.
The path separates the authorization response from other, potentially vulnerable paths within the same web application.
In flows using the web message response mode, the confidentiality of the authorization response is scoped to the postMessage's receiver origin that does not contain a path.
Thus, cross-site scripting (XSS) vulnerabilities on <em>any</em> path within the web application's origin will leak the authorization response to the attacker.</t>
</section>
</section>

<section anchor="IANA"><name>IANA Considerations</name>
<t>This draft makes no requests to IANA.</t>
</section>

</middle>

<back>
<references><name>Normative References</name>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.6749.xml"/>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8414.xml"/>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.9700.xml"/>
<reference anchor="oauth.encoding" target="https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html">
  <front>
    <title>OAuth 2.0 Multiple Response Type Encoding Practices</title>
    <author fullname="Breno de Medeiros" initials="B." surname="de Medeiros">
      <organization>Google</organization>
    </author>
    <author fullname="Marius Scurtescu" initials="M." surname="Scurtescu">
      <organization>Google</organization>
    </author>
    <author fullname="Paul Tarjan" initials="P." surname="Tarjan">
      <organization>Facebook</organization>
    </author>
    <author fullname="Michael B. Jones" initials="M." surname="Jones">
      <organization>Microsoft</organization>
    </author>
    <date year="2014" month="Feb"></date>
  </front>
</reference>
<reference anchor="whatwg.postmessage" target="https://html.spec.whatwg.org/multipage/web-messaging.html#web-messaging">
  <front>
    <title>HTML Living Standard: Cross-document messaging</title>
    <author></author>
    <date></date>
  </front>
</reference>
</references>
<references><name>Informative References</name>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml-ids/reference.I-D.sakimura-oauth-wmrm.xml"/>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.9126.xml"/>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.9396.xml"/>
<reference anchor="google.restrictprops" target="https://developer.chrome.com/blog/coop-restrict-properties/">
  <front>
    <title>Secure popup interactions with restrict-properties</title>
    <author></author>
    <author></author>
    <date year="2023" month="August" day="9"></date>
  </front>
</reference>
<reference anchor="mozilla.storageaccessapi" target="https://developer.mozilla.org/en-US/docs/Web/API/Storage_Access_API">
  <front>
    <title>Storage Access API</title>
    <author></author>
    <date year="2023" month="October" day="18"></date>
  </front>
</reference>
<reference anchor="oauth.post" target="http://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html">
  <front>
    <title>OAuth 2.0 Form Post Response Mode</title>
    <author fullname="Mike Jones" initials="M." surname="Jones">
      <organization>Microsoft</organization>
    </author>
    <author fullname="Brian Campbell" initials="B." surname="Campbell">
      <organization>Ping Identity</organization>
    </author>
    <date year="2015" month="April" day="27"></date>
  </front>
</reference>
<reference anchor="openid.core" target="https://openid.net/specs/openid-connect-core-1_0.html">
  <front>
    <title>OpenID Connect Core 1.0 incorporating errata set 1</title>
    <author fullname="Nat Sakimura" initials="N." surname="Sakimura">
      <organization>NRI</organization>
    </author>
    <author fullname="John Bradley" initials="J." surname="Bradley">
      <organization>Ping Identity</organization>
    </author>
    <author fullname="Mike Jones" initials="M." surname="Jones">
      <organization>Microsoft</organization>
    </author>
    <author fullname="Breno de Medeiros" initials="B." surname="de Medeiros">
      <organization>Google</organization>
    </author>
    <author fullname="Chuck Mortimore" initials="C." surname="Mortimore">
      <organization>Salesforce</organization>
    </author>
    <date year="2014" month="Nov" day="8"></date>
  </front>
</reference>
<reference anchor="w3c.observerv2" target="https://w3c.github.io/IntersectionObserver/">
  <front>
    <title>Intersection Observer</title>
    <author></author>
    <author></author>
    <date year="2019" month="November" day="4"></date>
  </front>
</reference>
<reference anchor="whatwg.coop" target="https://html.spec.whatwg.org/multipage/browsers.html#cross-origin-opener-policies">
  <front>
    <title>HTML Living Standard: Cross-origin opener policies</title>
    <author></author>
    <date></date>
  </front>
</reference>
</references>

<section anchor="Acknowledgements"><name>Acknowledgements</name>
<t>We would like to acknowledge the prior work of Toru Yamaguchi, Nat Sakimura, and Nov Matake in <xref target="I-D.sakimura-oauth-wmrm"></xref> which tried to define a response mode with similarities to this specification.
In contrast, this specification is not focused on iframes and does not include the use of the OAuth Implicit Grant.</t>
<t>We would like to thank Vladislav Mladenov, ...</t>
<t>for their valuable feedback on this document.</t>
</section>

<section anchor="document-history"><name>Document History</name>
<t>[[ To be removed from the final specification ]]</t>
<t>-01
* Add use cases of popup and iframe flows
* Enhance and clarify descriptions and mitigations for iframe flow
* Clarify iframe use for first-party context and invisible iframes for reauthentication flows with prompt none
* Add dynamic discovery of primary window reference and new values for response_mode: <tt>web_message.opener</tt> and <tt>web_message.parent</tt>
* Add notes about how this draft differs from Sakimura et al.
* Add several example implementations of the web message response mode and popup- or iframe-based flows
* Minor improvements of style and language
* Update references to newer versions</t>
<t>-00
* Initial draft</t>
</section>

<section anchor="example-implementations"><name>Example Implementations</name>
<t>[[ To be removed from the final specification ]]</t>
<t>Although neither the <tt>web_message</tt> response mode nor the popup- and iframe-based authorization flows have been officially standardized, they are already widely supported in practice.
A <eref target="https://dl.acm.org/doi/10.1145/3548606.3560692">study</eref> from late 2022 found that 153 of the Tranco Top 1k websites opened the authorization server in a secondary window, compared to only 134 websites that navigated the primary window to the authorization server.
More recently, a scan of all domains in the CrUX dataset (July 2025) revealed <eref target="https://github.com/Hackmanit/draft-meyerzuselha-oauth-web-message-response-mode/issues/27">22 authorization servers</eref> that publish the still-undefined <tt>web_message</tt> value in the <tt>response_modes_supported</tt> list of their <eref target="https://openid.net/specs/openid-connect-discovery-1_0.html">OpenID Provider Metadata</eref> at <tt>/.well-known/openid-configuration</tt>.
In addition, several authorization servers support popup- or iframe-based flows without explicitly announcing them in their metadata:</t>

<ul>
<li><t>Apple supports the popup-based flow with <tt>response_mode=web_message</tt> through its custom JS SDK.
The flow is activated if the client <eref target="https://developer.apple.com/documentation/signinwithapple/configuring-your-webpage-for-sign-in-with-apple">enables the SDK's popup mode via a meta tag</eref>.
Apple's <eref target="https://developer.apple.com/documentation/signinwithapplerestapi/request-an-authorization-to-the-sign-in-with-apple-server">REST API documentation</eref> does not mention <tt>web_message</tt> as a valid <tt>response_mode</tt>, although the SDK uses it when configured.</t>
</li>
<li><t>Google supports both the <eref target="https://developers.google.com/identity/gsi/web/guides/integrate#pop-up_versus_redirect">popup-based</eref> (default) and <eref target="https://developers.google.com/identity/gsi/web/amp/intermediate-iframe">iframe-based</eref> flows within its <eref target="https://developers.google.com/identity/gsi/web/guides/overview">Google Identity Services SDKs</eref>.
However, these flows are not available in its <eref target="https://developers.google.com/identity/protocols/oauth2/web-server">interoperable OAuth and OpenID Connect endpoints</eref>.</t>
</li>
<li><t>Facebook supports the popup-based flow through its <eref target="https://developers.facebook.com/docs/facebook-login/web">JS SDK</eref>.
It always includes the <tt>xd_arbiter</tt> endpoint as a parameter to the authorization endpoint, e.g., <tt>channel_url=https://staticxx.facebook.com/x/connect/xd_arbiter</tt>.</t>
</li>
<li><t>Auth0 officially documents support for the <tt>web_message</tt> response mode in its <eref target="https://auth0.com/docs/authenticate/protocols/oauth">API documentation</eref>.
It references the expired draft <xref target="I-D.sakimura-oauth-wmrm"></xref> from 2015 and uses it for silent authentication with HTML5 web messaging.</t>
</li>
<li><t>Nintendo uses the <tt>web_message</tt> response mode internally, following the expired draft <xref target="I-D.sakimura-oauth-wmrm"></xref>.
It also relies on the additional <tt>web_message_uri</tt> and <tt>web_message_target</tt> parameters.</t>
</li>
</ul>
<t>Beyond these providers, other authorization servers also employ <tt>web_message</tt> or proprietary variants of popup- and iframe-based flows.
Apple, Google, and Facebook even make multi-window flows the default within their SDKs, highlighting their practical importance.
Yet, the absence of an interoperable, standards-based mechanism for clients to use these flows underscores the need for formal standardization.</t>
</section>

<section anchor="differences-to-i-d-sakimura-oauth-wmrm"><name>Differences to <xref target="I-D.sakimura-oauth-wmrm"></xref></name>
<t>[[ To be removed from the final specification ]]</t>
<t>This draft builds on the earlier work of Toru Yamaguchi, Nat Sakimura, and Nov Matake in <xref target="I-D.sakimura-oauth-wmrm"></xref>, which introduced a web message response mode.
While sharing several conceptual similarities, this draft differs in the following ways:</t>

<ul>
<li><t><strong>Flow illustrations:</strong>
<xref target="I-D.sakimura-oauth-wmrm"></xref> illustrates only the deprecated implicit flow (<tt>response_type=token</tt>).
This draft is flow-agnostic and uses the authorization code flow (<tt>response_type=code</tt>) in its examples.</t>
</li>
<li><t><strong>Primary window reference:</strong>
<xref target="I-D.sakimura-oauth-wmrm"></xref> does not specify how the authorization server should obtain a reference to the client's primary window.
This draft allows the authorization server to either dynamically discover the reference or rely on client-provided hints via the <tt>web_message.opener</tt> and <tt>web_message.parent</tt> response modes.</t>
</li>
<li><t><strong>Relay mode:</strong>
<xref target="I-D.sakimura-oauth-wmrm"></xref> defines a relay mode in which the authorization response is forwarded through the client to a third window (the &quot;message target window&quot;).
This draft does not support tertiary windows and instead limits the exchange to the client's primary window and the authorization server's secondary window.
This draft omits relay mode due to lack of practical demand.</t>
</li>
<li><t><strong>Browser compatibility:</strong>
<xref target="I-D.sakimura-oauth-wmrm"></xref> uses JavaScript constructs that no longer work in modern browsers (e.g., <tt>window.opener != window</tt> and cross-origin DOM access via <tt>evt.source.document.getElementById</tt>).
These break relay mode entirely, as the secondary window cannot obtain a reference to the message target window.</t>
</li>
<li><t><strong>Parameters:</strong>
<xref target="I-D.sakimura-oauth-wmrm"></xref> introduces the <tt>web_message_uri</tt> (target URI) and <tt>web_message_target</tt> (DOM id) parameters, both tied to relay mode.
This draft omits these parameters and instead relies solely on the established <tt>redirect_uri</tt>.</t>
</li>
<li><t><strong>Message format:</strong>
<xref target="I-D.sakimura-oauth-wmrm"></xref> defines <tt>postMessage</tt> data as an object with fields <tt>type</tt> (string) and <tt>response</tt> (object).
This draft simplifies the structure to a single object containing all authorization response parameters, since only one <tt>postMessage</tt> is used.</t>
</li>
<li><t><strong>Iframe restrictions:</strong>
<xref target="I-D.sakimura-oauth-wmrm"></xref> restricts iframe-based flows to already-authenticated sessions with prior consent (&quot;authenticated windows&quot;).
This draft permits iframe-based flows in unauthenticated states as well, relying on Clickjacking mitigations (e.g., the Intersection Observer v2 API).</t>
</li>
<li><t><strong>Security considerations:</strong>
This draft provides extended guidance on secure use of <tt>postMessage</tt>, Clickjacking mitigations, and implications of browsers phasing out third-party cookies.</t>
</li>
</ul>
</section>

</back>

</rfc>
