<?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-00" 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-00" 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>

<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 use the user-agent's postMessage API to return the authorization response to the client.</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 the security best practices <xref target="I-D.ietf-oauth-security-topics"></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">========== NOTE: '\' line wrapping per RFC 8792 ===========

const primaryWindowRef = window.opener // popup-based auth. flow
const primaryWindowRef = window.parent // iframe-based auth. flow
primaryWindowRef.postMessage({&quot;code&quot;: &quot;XXXXXXXX&quot;,&quot;state&quot;:&quot;XXXXXXXX&quot;,\
&quot;iss&quot;: &quot;https://as.example&quot;},&quot;https://client.example/cb&quot;)
</sourcecode>
</section>

<section anchor="popup-based-authorization-flow-using-the-web-message-response-mode"><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 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>.
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 might 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">========== NOTE: '\' line wrapping per RFC 8792 ===========

window.open(&quot;https://as.example/auth?...&amp;response_mode=web_message&quot;,\
&quot;_blank&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">========== NOTE: '\' line wrapping per RFC 8792 ===========

&lt;a href=&quot;https://as.example/auth?...&amp;response_mode=web_message&quot; \
target=&quot;_blank&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>, 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 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">========== NOTE: '\' line wrapping per RFC 8792 ===========

window.opener.postMessage({&quot;code&quot;: &quot;XXXXXXXX&quot;, &quot;state&quot;: &quot;XXXXXXXX&quot;, \
&quot;iss&quot;: &quot;https://as.example&quot;}, &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 the security best practices <xref target="I-D.ietf-oauth-security-topics"></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.
Iframes enable a seamless authorization flow where the end-user only sees a single browser tab, without ever leaving the actual client.
The exchange of tokens works technically similar to popups.
However, iframes are more difficult to implement on the authorization server side.</t>
</section>

<section anchor="secure-iframe-integration"><name>Secure Iframe Integration</name>
<t>An authorization endpoint and consent-page embedded in an iframe MUST be protected against Clickjacking attacks <xref target="I-D.ietf-oauth-security-topics" sectionFormat="parens" relative="#" section="4.16"></xref>.</t>
<t>If the user's browser supports the 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.
Otherwise, the authorization server MUST implement Clickjacking countermeasures according to <xref target="I-D.ietf-oauth-security-topics" sectionFormat="parens" relative="#" section="4.16"></xref>. The authorization server MUST prevent framing the authorization endpoint and consent-page except from origins deemed trustworthy.</t>

<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>
</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> 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>.</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 the security best practices <xref target="I-D.ietf-oauth-security-topics" sectionFormat="parens" relative="#" section="4.18.2"></xref>
when validating the postMessage receiver origin.
Otherwise, the authorization response may leak to an attacker,
as described in <xref target="I-D.ietf-oauth-security-topics" sectionFormat="parens" relative="#" section="4.18.1.1"></xref> and <xref target="I-D.ietf-oauth-security-topics" sectionFormat="parens" relative="#" section="4.18.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="I-D.ietf-oauth-security-topics" 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 the security best practices <xref target="I-D.ietf-oauth-security-topics" sectionFormat="parens" relative="#" section="4.18.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="I-D.ietf-oauth-security-topics" sectionFormat="parens" relative="#" section="4.18.1.3"></xref>.
This verification prevents some variants of CSRF attacks, where the attacker wants to log in a victim to the attacker 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="I-D.ietf-oauth-security-topics" 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 specific, 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-ids/reference.I-D.ietf-oauth-security-topics.xml"/>
<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"/>
<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="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>-00
*  initial draft</t>
</section>

</back>

</rfc>
