<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head profile="http://www.w3.org/2006/03/hcard http://dublincore.org/documents/2008/08/04/dc-html/">
  <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />

  <title>OAuth 2.0 IDP-IFrame-based Implicit Flow</title>

  <style type="text/css" title="Xml2Rfc (sans serif)">
  /*<![CDATA[*/
          a {
          text-decoration: none;
          }
      /* info code from SantaKlauss at http://www.madaboutstyle.com/tooltip2.html */
      a.info {
          /* This is the key. */
          position: relative;
          z-index: 24;
          text-decoration: none;
      }
      a.info:hover {
          z-index: 25;
          color: #FFF; background-color: #900;
      }
      a.info span { display: none; }
      a.info:hover span.info {
          /* The span will display just on :hover state. */
          display: block;
          position: absolute;
          font-size: smaller;
          top: 2em; left: -5em; width: 15em;
          padding: 2px; border: 1px solid #333;
          color: #900; background-color: #EEE;
          text-align: left;
      }
          a.smpl {
          color: black;
          }
          a:hover {
          text-decoration: underline;
          }
          a:active {
          text-decoration: underline;
          }
          address {
          margin-top: 1em;
          margin-left: 2em;
          font-style: normal;
          }
          body {
          color: black;
          font-family: verdana, helvetica, arial, sans-serif;
          font-size: 10pt;
          max-width: 55em;
          
          }
          cite {
          font-style: normal;
          }
          dd {
          margin-right: 2em;
          }
          dl {
          margin-left: 2em;
          }
        
          ul.empty {
          list-style-type: none;
          }
          ul.empty li {
          margin-top: .5em;
          }
          dl p {
          margin-left: 0em;
          }
          dt {
          margin-top: .5em;
          }
          h1 {
          font-size: 14pt;
          line-height: 21pt;
          page-break-after: avoid;
          }
          h1.np {
          page-break-before: always;
          }
          h1 a {
          color: #333333;
          }
          h2 {
          font-size: 12pt;
          line-height: 15pt;
          page-break-after: avoid;
          }
          h3, h4, h5, h6 {
          font-size: 10pt;
          page-break-after: avoid;
          }
          h2 a, h3 a, h4 a, h5 a, h6 a {
          color: black;
          }
          img {
          margin-left: 3em;
          }
          li {
          margin-left: 2em;
          margin-right: 2em;
          }
          ol {
          margin-left: 2em;
          margin-right: 2em;
          }
          ol p {
          margin-left: 0em;
          }
          p {
          margin-left: 2em;
          margin-right: 2em;
          }
          pre {
          margin-left: 3em;
          background-color: lightyellow;
          padding: .25em;
          }
          pre.text2 {
          border-style: dotted;
          border-width: 1px;
          background-color: #f0f0f0;
          width: 69em;
          }
          pre.inline {
          background-color: white;
          padding: 0em;
          }
          pre.text {
          border-style: dotted;
          border-width: 1px;
          background-color: #f8f8f8;
          width: 69em;
          }
          pre.drawing {
          border-style: solid;
          border-width: 1px;
          background-color: #f8f8f8;
          padding: 2em;
          }
          table {
          margin-left: 2em;
          }
          table.tt {
          vertical-align: top;
          }
          table.full {
          border-style: outset;
          border-width: 1px;
          }
          table.headers {
          border-style: outset;
          border-width: 1px;
          }
          table.tt td {
          vertical-align: top;
          }
          table.full td {
          border-style: inset;
          border-width: 1px;
          }
          table.tt th {
          vertical-align: top;
          }
          table.full th {
          border-style: inset;
          border-width: 1px;
          }
          table.headers th {
          border-style: none none inset none;
          border-width: 1px;
          }
          table.left {
          margin-right: auto;
          }
          table.right {
          margin-left: auto;
          }
          table.center {
          margin-left: auto;
          margin-right: auto;
          }
          caption {
          caption-side: bottom;
          font-weight: bold;
          font-size: 9pt;
          margin-top: .5em;
          }
        
          table.header {
          border-spacing: 1px;
          width: 95%;
          font-size: 10pt;
          color: white;
          }
          td.top {
          vertical-align: top;
          }
          td.topnowrap {
          vertical-align: top;
          white-space: nowrap; 
          }
          table.header td {
          background-color: gray;
          width: 50%;
          }
          table.header a {
          color: white;
          }
          td.reference {
          vertical-align: top;
          white-space: nowrap;
          padding-right: 1em;
          }
          thead {
          display:table-header-group;
          }
          ul.toc, ul.toc ul {
          list-style: none;
          margin-left: 1.5em;
          margin-right: 0em;
          padding-left: 0em;
          }
          ul.toc li {
          line-height: 150%;
          font-weight: bold;
          font-size: 10pt;
          margin-left: 0em;
          margin-right: 0em;
          }
          ul.toc li li {
          line-height: normal;
          font-weight: normal;
          font-size: 9pt;
          margin-left: 0em;
          margin-right: 0em;
          }
          li.excluded {
          font-size: 0pt;
          }
          ul p {
          margin-left: 0em;
          }
        
          .comment {
          background-color: yellow;
          }
          .center {
          text-align: center;
          }
          .error {
          color: red;
          font-style: italic;
          font-weight: bold;
          }
          .figure {
          font-weight: bold;
          text-align: center;
          font-size: 9pt;
          }
          .filename {
          color: #333333;
          font-weight: bold;
          font-size: 12pt;
          line-height: 21pt;
          text-align: center;
          }
          .fn {
          font-weight: bold;
          }
          .hidden {
          display: none;
          }
          .left {
          text-align: left;
          }
          .right {
          text-align: right;
          }
          .title {
          color: #990000;
          font-size: 18pt;
          line-height: 18pt;
          font-weight: bold;
          text-align: center;
          margin-top: 36pt;
          }
          .vcardline {
          display: block;
          }
          .warning {
          font-size: 14pt;
          background-color: yellow;
          }
        
        
          @media print {
          .noprint {
                display: none;
          }
        
          a {
                color: black;
                text-decoration: none;
          }
        
          table.header {
                width: 90%;
          }
        
          td.header {
                width: 50%;
                color: black;
                background-color: white;
                vertical-align: top;
                font-size: 12pt;
          }
        
          ul.toc a::after {
                content: leader('.') target-counter(attr(href), page);
          }
        
          ul.ind li li a {
                content: target-counter(attr(href), page);
          }
        
          .print2col {
                column-count: 2;
                -moz-column-count: 2;
                column-fill: auto;
          }
          }
        
          @page {
          @top-left {
                   content: "Internet-Draft"; 
          } 
          @top-right {
                   content: "December 2010"; 
          } 
          @top-center {
                   content: "Abbreviated Title";
          } 
          @bottom-left {
                   content: "Doe"; 
          } 
          @bottom-center {
                   content: "Expires June 2011"; 
          } 
          @bottom-right {
                   content: "[Page " counter(page) "]"; 
          } 
          }
        
          @page:first { 
                @top-left {
                  content: normal;
                }
                @top-right {
                  content: normal;
                }
                @top-center {
                  content: normal;
                }
          }
  /*]]>*/
  </style>

  <link href="#rfc.toc" rel="Contents"/>
<link href="#rfc.section.1" rel="Chapter" title="1 Introduction"/>
<link href="#rfc.section.1.1" rel="Chapter" title="1.1 Notational Conventions"/>
<link href="#rfc.section.1.2" rel="Chapter" title="1.2 Terminology"/>
<link href="#rfc.section.1.3" rel="Chapter" title="1.3 Architecture Overview"/>
<link href="#rfc.section.1.4" rel="Chapter" title="1.4 IDP-IFrame-based Implicit Flow"/>
<link href="#rfc.section.1.5" rel="Chapter" title="1.5 Login Hint"/>
<link href="#rfc.section.1.6" rel="Chapter" title="1.6 Session Selector"/>
<link href="#rfc.section.1.6.1" rel="Chapter" title="1.6.1 Default Domain Access Policy"/>
<link href="#rfc.section.1.7" rel="Chapter" title="1.7 storagerelay Scheme URI"/>
<link href="#rfc.section.1.8" rel="Chapter" title="1.8 Parameters Naming Rules"/>
<link href="#rfc.section.2" rel="Chapter" title="2 IDP IFrame"/>
<link href="#rfc.section.2.1" rel="Chapter" title="2.1 Embed IDP IFrame Into A Container Page"/>
<link href="#rfc.section.2.1.1" rel="Chapter" title="2.1.1 IDP IFrame Initialization Parameters"/>
<link href="#rfc.section.2.2" rel="Chapter" title="2.2 Provisioning"/>
<link href="#rfc.section.2.3" rel="Chapter" title="2.3 RPCs"/>
<link href="#rfc.section.2.3.1" rel="Chapter" title="2.3.1 monitorClient"/>
<link href="#rfc.section.2.3.2" rel="Chapter" title="2.3.2 getSessionSelector"/>
<link href="#rfc.section.2.3.3" rel="Chapter" title="2.3.3 setSessionSelector"/>
<link href="#rfc.section.2.3.4" rel="Chapter" title="2.3.4 getTokenResponse"/>
<link href="#rfc.section.2.3.5" rel="Chapter" title="2.3.5 listIdpSessions"/>
<link href="#rfc.section.2.3.6" rel="Chapter" title="2.3.6 revoke"/>
<link href="#rfc.section.2.4" rel="Chapter" title="2.4 Events"/>
<link href="#rfc.section.2.4.1" rel="Chapter" title="2.4.1 SessionStateChanged"/>
<link href="#rfc.section.2.4.2" rel="Chapter" title="2.4.2 SessionSelectorChanged"/>
<link href="#rfc.section.2.4.3" rel="Chapter" title="2.4.3 AuthResult"/>
<link href="#rfc.section.3" rel="Chapter" title="3 Authorization Endpoint"/>
<link href="#rfc.section.3.1" rel="Chapter" title="3.1 Permission Response Type"/>
<link href="#rfc.section.3.1.1" rel="Chapter" title="3.1.1 Permission Request"/>
<link href="#rfc.section.3.1.2" rel="Chapter" title="3.1.2 Permission Response"/>
<link href="#rfc.section.3.2" rel="Chapter" title="3.2 storagerelay Scheme URI"/>
<link href="#rfc.section.4" rel="Chapter" title="4 Privacy Considerations"/>
<link href="#rfc.section.5" rel="Chapter" title="5 Security Considerations"/>
<link href="#rfc.references" rel="Chapter" title="6 Normative References"/>
<link href="#rfc.appendix.A" rel="Chapter" title="A Acknowledgements"/>
<link href="#rfc.authors" rel="Chapter"/>


  <meta name="generator" content="xml2rfc version 2.5.1.dev0 - http://tools.ietf.org/tools/xml2rfc" />
  <link rel="schema.dct" href="http://purl.org/dc/terms/" />

  <meta name="dct.creator" content="Kong, G., Agarwal, N., and W. Denniss" />
  <meta name="dct.identifier" content="urn:ietf:id:draft-guibinkong-oauth-idp-iframe-00" />
  <meta name="dct.issued" scheme="ISO8601" content="2015-11-21" />
  <meta name="dct.abstract" content="In this document, we define a new architecture and flow for JavaScript clients on how to get access tokens and/or ID tokens from Identity providers (IDP).  Instead of getting these tokens from the IDP Authorization Endpoint (as defined in " />
  <meta name="description" content="In this document, we define a new architecture and flow for JavaScript clients on how to get access tokens and/or ID tokens from Identity providers (IDP).  Instead of getting these tokens from the IDP Authorization Endpoint (as defined in " />

</head>

<body>

  <table class="header">
    <tbody>
    
        <tr>
  <td class="left">OAuth Working Group</td>
  <td class="right">G. Kong</td>
</tr>
<tr>
  <td class="left">Internet-Draft</td>
  <td class="right">N. Agarwal</td>
</tr>
<tr>
  <td class="left">Intended status: Standards Track</td>
  <td class="right">W. Denniss</td>
</tr>
<tr>
  <td class="left">Expires: May 24, 2016</td>
  <td class="right">Google</td>
</tr>
<tr>
  <td class="left"></td>
  <td class="right">November 21, 2015</td>
</tr>

        
    </tbody>
  </table>

  <p class="title">OAuth 2.0 IDP-IFrame-based Implicit Flow<br />
  <span class="filename">draft-guibinkong-oauth-idp-iframe-00</span></p>
  
  <h1 id="rfc.abstract">
  <a href="#rfc.abstract">Abstract</a>
</h1>
<p>In this document, we define a new architecture and flow for JavaScript clients on how to get access tokens and/or ID tokens from Identity providers (IDP).  Instead of getting these tokens from the IDP Authorization Endpoint (as defined in <a href="#RFC6749">RFC 6749</a> <cite title="NONE">[RFC6749]</cite> as the token flow), JavaScript clients now get these tokens from an IFrame provided by the IDP.  This change brings huge performance and security benefits.  </p>
<p>On the performance aspect, the IDP IFrame can transparently cache these tokens in IDP Web Storage.  On page reload or navigation, the cached tokens may be returned to Relying party (RP) without any request to IDP.  This can avoid the huge traffic to the IDP authorization endpoint, and improve RP page latency.  </p>
<p>On the security aspect, when sending the tokens from IDP domain to RP domain, HTML5 postMessage is used, instead of the HTTP redirection.  The source origin and target origin of HTML5 postMessage are trustable, which is not the case for HTTP redirection.  This change mitigates most HTTP redirection related attacks, and makes cross site request forgery (XSRF) attacks much harder.  </p>
<p>This specification also defines a powerful and ready-to-use session management API for JavaScript clients.  1)The IDP IFrame can syndicate IDP session state to clients.  Clients will get notified when the user who issued the tokens signs out in the IDP domain, and when the user signs in again.  2)To work nice with multiLogin IDPs like Google, the IDP IFrame also provides APIs to enumerate IDP sessions, to sync session selection across RP domain and sub domains.  3)RP-side logout is also supported, in which case clients stay in logout/disabled state even after page reload.  </p>
<p>Unlike the token flow, which only focuses on permission granting and token issuing, this specification defines the full life cycle APIs for JavaScript clients, from permission granting, token issuing, session management, to permission revocation.  Ideally JavaScript clients can fulfill all OAuth 2.0 related operations using this specification.  </p>
<p>This specification makes it possible that RP can use one unified JavaScript client library to access any compliant IDPs.  It is hard to achieve this goal in the past because the session management and token caching parts were not standardized before.  </p>
<p>The architecture and flow defined in this specification should work fine on any environment that allows IFrame embedding, and supports Web Storage and postMessage.  Based on this assumption, this specification can be used in normal web and chrome extension context.  </p>
<h1 id="rfc.status">
  <a href="#rfc.status">Status of This Memo</a>
</h1>
<p>This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.</p>
<p>Internet-Drafts are working documents of the Internet Engineering Task Force (IETF).  Note that other groups may also distribute working documents as Internet-Drafts.  The list of current Internet-Drafts is at http://datatracker.ietf.org/drafts/current/.</p>
<p>Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time.  It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."</p>
<p>This Internet-Draft will expire on May 24, 2016.</p>
<h1 id="rfc.copyrightnotice">
  <a href="#rfc.copyrightnotice">Copyright Notice</a>
</h1>
<p>Copyright (c) 2015 IETF Trust and the persons identified as the document authors.  All rights reserved.</p>
<p>This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document.  Please review these documents carefully, as they describe your rights and restrictions with respect to this document.  Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.</p>

  
  <hr class="noprint" />
  <h1 class="np" id="rfc.toc"><a href="#rfc.toc">Table of Contents</a></h1>
  <ul class="toc">

        <li>1.   <a href="#rfc.section.1">Introduction</a></li>
<ul><li>1.1.   <a href="#rfc.section.1.1">Notational Conventions</a></li>
<li>1.2.   <a href="#rfc.section.1.2">Terminology</a></li>
<li>1.3.   <a href="#rfc.section.1.3">Architecture Overview</a></li>
<li>1.4.   <a href="#rfc.section.1.4">IDP-IFrame-based Implicit Flow</a></li>
<li>1.5.   <a href="#rfc.section.1.5">Login Hint</a></li>
<li>1.6.   <a href="#rfc.section.1.6">Session Selector</a></li>
<ul><li>1.6.1.   <a href="#rfc.section.1.6.1">Default Domain Access Policy</a></li>
</ul><li>1.7.   <a href="#rfc.section.1.7">storagerelay Scheme URI</a></li>
<li>1.8.   <a href="#rfc.section.1.8">Parameters Naming Rules</a></li>
</ul><li>2.   <a href="#rfc.section.2">IDP IFrame</a></li>
<ul><li>2.1.   <a href="#rfc.section.2.1">Embed IDP IFrame Into A Container Page</a></li>
<ul><li>2.1.1.   <a href="#rfc.section.2.1.1">IDP IFrame Initialization Parameters</a></li>
</ul><li>2.2.   <a href="#rfc.section.2.2">Provisioning</a></li>
<li>2.3.   <a href="#rfc.section.2.3">RPCs</a></li>
<ul><li>2.3.1.   <a href="#rfc.section.2.3.1">monitorClient</a></li>
<li>2.3.2.   <a href="#rfc.section.2.3.2">getSessionSelector</a></li>
<li>2.3.3.   <a href="#rfc.section.2.3.3">setSessionSelector</a></li>
<li>2.3.4.   <a href="#rfc.section.2.3.4">getTokenResponse</a></li>
<li>2.3.5.   <a href="#rfc.section.2.3.5">listIdpSessions</a></li>
<li>2.3.6.   <a href="#rfc.section.2.3.6">revoke</a></li>
</ul><li>2.4.   <a href="#rfc.section.2.4">Events</a></li>
<ul><li>2.4.1.   <a href="#rfc.section.2.4.1">SessionStateChanged</a></li>
<li>2.4.2.   <a href="#rfc.section.2.4.2">SessionSelectorChanged</a></li>
<li>2.4.3.   <a href="#rfc.section.2.4.3">AuthResult</a></li>
</ul></ul><li>3.   <a href="#rfc.section.3">Authorization Endpoint</a></li>
<ul><li>3.1.   <a href="#rfc.section.3.1">Permission Response Type</a></li>
<ul><li>3.1.1.   <a href="#rfc.section.3.1.1">Permission Request</a></li>
<li>3.1.2.   <a href="#rfc.section.3.1.2">Permission Response</a></li>
</ul><li>3.2.   <a href="#rfc.section.3.2">storagerelay Scheme URI</a></li>
</ul><li>4.   <a href="#rfc.section.4">Privacy Considerations</a></li>
<li>5.   <a href="#rfc.section.5">Security Considerations</a></li>
<li>6.   <a href="#rfc.references">Normative References</a></li>
<li>Appendix A.   <a href="#rfc.appendix.A">Acknowledgements</a></li>
<li><a href="#rfc.authors">Authors' Addresses</a></li>


  </ul>

  <h1 id="rfc.section.1"><a href="#rfc.section.1">1.</a> <a href="#introduction" id="introduction">Introduction</a></h1>
<p id="rfc.section.1.p.1">The objectives of this specification are to improve security and make caching of tokens transparent to relying parties.  It mitigates the following concerns related to the token flow defined in the OAuth 2.0 [<a href="#RFC6749">RFC 6749</a> <cite title="NONE">[RFC6749]</cite>].  <a href="#RFC6749">RFC 6749</a> <cite title="NONE">[RFC6749]</cite>.  </p>

<dl>
  <dt>1)</dt>
  <dd style="margin-left: 8">Security risk caused by HTTP Redirection.  Whenever an open-redirection bug is found in the relying party (RP) domain, it can be used to relay the access token in the URL fragment to malicious URLs controlled by attackers.  This has caused several publicly reported security incidents in the past, and contributed to negative perceptions of the security of the OAuth 2.0 protocol.  </dd>
  <dt>2)</dt>
  <dd style="margin-left: 8">Security risk for Cross Site Request Forgery (XSRF).  Due to the inability to verify the origination of the HTTP redirection, clients must leverage other measures (like the state parameter) to make sure the response is not forged.  This is awkward for pure JavaScript clients, since additional work is needed to generate a secure state value and persist it in Web Storage.  </dd>
  <dt>3)</dt>
  <dd style="margin-left: 8">Performance issues.  The token flow doesn't define how to cache access token for reuse.  Serious performance issues may be caused in both RP side and IDP side, if the client attempts to get a new access token from the IDP Authorization Endpoint on each page reload.  RP page latency may increase dramatically, and IDP may need to handle lots of unnecessary traffic.  </dd>
  <dt>4)</dt>
  <dd style="margin-left: 8">Session Confusion.  Clients need to get a new access token when the old one expires, normally by retrying the token flow in immediate mode.  If IDP session has changed during that period (and if both sessions have approved the client), the new access token for another user will be returned silently.  Unless additional measures taken, RP wouldn't notice the session change in the IDP side, and thus cause session confusion.  </dd>
  <dt>5)</dt>
  <dd style="margin-left: 8">Popup mode support.  For UX reasons, RP may want to open the IDP authorization page in a popup window.  The token flow doesn't support popup mode directly. RP must setup a callback endpoint to relay the authorization response to the main window.  </dd>
  <dt>6)</dt>
  <dd style="margin-left: 8">Work with Multiple Signed-In Sessions.  Some IDPs, like Google, support multiple simultaneously signed-in users (wMultiLogin).  RP needs to remember the active session user selected to avoid prompting the session selection page to end user on each page reload.  Also, if RP has sub domains, the session selection must be shared across sub-domains.  </dd>
  <dt>7)</dt>
  <dd style="margin-left: 8">Security risk caused by token caching in RP side.  To fix the performance issues mentioned above, some RP may maintain a Web-Storage-based cache in RP domain.  This solution may scatter the security-sensitive tokens across lots of RP domains, some of which may lack good Web Storage protection.  And it is hard to clean the tokens immediately when user logs out on IDP side.  </dd>
  <dt>8)</dt>
  <dd style="margin-left: 8">Developer experience issues.  The OAuth 2.0 specification [RFC6749] defines just a framework, which only provides common solution for part of the problems a developer is facing when using OAuth 2.0.  IDPs may extend the framework in different way, and may provide their own client libraries.  Developers need to investigate and include different client libraries for different IDPs.  Sometimes the libraries don't provide full lifecycle support, for example token revocation API may be missing in some IDP libraries.  Also the libraries may not work well in Chrome extension context.  In short, it is hard to provide a unified client library that can access all compliant IDPs with full lifecycle support APIs from both web and chrome extension context.  </dd>
</dl>

<p> To mitigate above issues, this specification defines a new architecture and flow for JavaScript clients, and proposes to replace and obsolete the OAuth 2.0 token flow described in </p>
<h1 id="rfc.section.1.1"><a href="#rfc.section.1.1">1.1.</a> <a href="#notational_conventions" id="notational_conventions">Notational Conventions</a></h1>
<p id="rfc.section.1.1.p.1">The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in Key words for use in RFCs to Indicate Requirement Levels <a href="#RFC2119">[RFC2119]</a>.  If these words are used without being spelled in uppercase then they are to be interpreted with their normal natural language meanings.  </p>
<h1 id="rfc.section.1.2"><a href="#rfc.section.1.2">1.2.</a> <a href="#terminology" id="terminology">Terminology</a></h1>
<p id="rfc.section.1.2.p.1">This specification uses the terms "Access Token", "Authorization Code", "Authorization Endpoint", "Authorization Grant", "Authorization Server", "Client", "Client Authentication", "Client Identifier", "Client Secret", "Grant Type", "Protected Resource", "Redirection URI", "Refresh Token", "Resource Owner", "Resource Server", "Response Type", and "Token Endpoint" defined byOAuth 2.0 [RFC6749], the term "User Agent" defined by RFC 2616 [RFC2616].  </p>
<p id="rfc.section.1.2.p.2">This specification also defines the following terms: </p>
<p/>

<dl>
  <dt>"Authorization Code Flow"</dt>
  <dd style="margin-left: 8">OAuth 2.0 flow in which an Authorization Code is returned from the Authorization Endpoint and all tokens are returned from the Token Endpoint.  </dd>
  <dt>"Authorization Request"</dt>
  <dd style="margin-left: 8">OAuth 2.0 Authorization Request as defined by [RFC6749].  </dd>
  <dt>"Container Page"</dt>
  <dd style="margin-left: 8">The page that embeds the IDP IFrame.  </dd>
  <dt>"ID Token"</dt>
  <dd style="margin-left: 8">JSON Web Token (JWT) [JWT] that contains Claims about the Authentication event. It MAY contain other Claims.  </dd>
  <dt>"IDP IFrame"</dt>
  <dd style="margin-left: 8">IDP IFrame is a hidden IFrame provided by IDP, which can be embedded into a container page in third party domain, and provides OAuth 2.0 token and session services on behalf of the IDP for the JavaScript clients that are running in the container page.  </dd>
  <dt>"Login Hint"</dt>
  <dd style="margin-left: 8">An opaque string that can uniquely identify a user. It is used to keep track of the bound user in the RP side in this specification.  </dd>
  <dt>"OpenID Provider (IDP)"</dt>
  <dd style="margin-left: 8">OAuth 2.0 Authorization Server that is capable of Authenticating the End-User and providing Claims to a Relying Party about the Authentication event and the End-User.  </dd>
  <dt>"Personally Identifiable Information (PII)"</dt>
  <dd style="margin-left: 8">Information that (a) can be used to identify the natural person to whom such information relates, or (b) is or might be directly or indirectly linked to a natural person to whom such information relates.  </dd>
  <dt>"Relying Party (RP)"</dt>
  <dd style="margin-left: 8">OAuth 2.0 Client application requiring End-User Authentication and Claims from an OpenID Provider.  </dd>
  <dt>"RP side logout"</dt>
  <dd style="margin-left: 8">The RP stays in logout state even if the bound user has an active session on the IDP side.  The logout state means that RP won't try to get an access token or redirect to IDP automatically.  The RP side logout state should be persistent in some way, so that it stays in this state after page reload.  </dd>
  <dt>"Session Selector"</dt>
  <dd style="margin-left: 8">The private storage provided by IDP IFrame for an RP, to track the session selection and session state. The session selector may be shared by sub domains decided by the configuration.  </dd>
  <dt>"Storagerelay Scheme URI"</dt>
  <dd style="margin-left: 8">A special URI to indicate the authorization response should be relayed via HTML5 Web Storage.  </dd>
  <dt>"Token Flow"</dt>
  <dd style="margin-left: 8">OAuth 2.0 flow in which all tokens are returned from the Authorization Endpoint and neither the Token Endpoint nor an Authorization Code are used.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.1.3"><a href="#rfc.section.1.3">1.3.</a> <a href="#architecture_overview" id="architecture_overview">Architecture Overview</a></h1>
<p id="rfc.section.1.3.p.1">This specification defines a new architecture for OAuth 2.0 implicit flow.  </p>
<p/>

<dl>
  <dt>1)</dt>
  <dd style="margin-left: 8">IDP must host an IDP IFrame page, which can be embedded into third party site pages, and receive cross origin message from the embedding domain via HTML5 postMessage.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">The IDP IFrame can respond to some predefined messages (RPCs); also it can sends some pre-defined messages (Events) to clients when some states change in the IDP IFrame.  </dd>
  <dt>2)</dt>
  <dd style="margin-left: 8">Access tokens MUST be issued from the IDP IFrame. For this specification, access tokens MUST NOT be returned from authorization endpoint via HTTP redirection.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">The access tokens SHOULD be automatically cached in the IDP IFrame sessionStorage.  The clients always use the same API to get the token response, and don't need to understand how the cache in the IDP IFrame operates.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">When requesting access tokens, the login hint of the bound user MUST be included in the request.  The access tokens MUST NOT be returned if the bound user doesn't have an active session in the IDP side at that time.  </dd>
  <dt>3)</dt>
  <dd style="margin-left: 8">Login hint is used to keep track of the bound user.  The login hint SHOULD be persistent in the IDP IFrame, in a storage private to current RP, and MAY be shared by its sub domains.  The private storage provided by IDP IFrame for an RP is called Session Selector.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">The IDP IFrame provides APIs to read and write the data in the session selector.  The RP origin will be checked to decide if an RP has the permission to operate on a session selector.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">If the session selector is changed by a client in one tab, other clients (no matter in the same or different tabs), will be notified by a SessionSelectorChanged event.  Once receiving that event, clients should drop the old tokens immediately, and request tokens for the new bound user.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">To support RP side logout, a 'disabled' field is also stored in the session selector.  The SessionSelectorChanged event handler should also check that field when deciding RP session state.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">Session Selector provides a single place to manage the session selection and session state in a multiple clients, multiple tabs, and multiple sub domains context, which dramatically decreases the chance of session confusion.  </dd>
  <dt>4)</dt>
  <dd style="margin-left: 8">The IDP IFrame will monitor the session state of the bound user in the IDP site.  When the session state changes, a SessionStateChanged event will be fired to notify the client.  This allows the client in RP domain to syndicate to the IDP session state, so as to start to run right after the bound user logged in; and stop to run right after the bound user logged out.  </dd>
  <dt>5)</dt>
  <dd style="margin-left: 8">In popup mode, the authorization response in the popup window can be sent to the IDP IFrame in the main window via web storage event.  Then the IDP IFrame can relay it to the RP by an AuthResult event.  The storagerelay URL scheme is defined to support this type of communication.  </dd>
  <dt>6)</dt>
  <dd style="margin-left: 8">To provide full lifecycle API support, clients can also get an one-time-use code; list IDP sessions; revoke permission via the IDP IFrame.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.1.4"><a href="#rfc.section.1.4">1.4.</a> <a href="#flow" id="flow">IDP-IFrame-based Implicit Flow</a></h1>
<pre>
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 |         System Browser          |
 |                                 |
 | +----------------------------+  |  (4) request      +----------+
 | |                            |  |   permission      |          |
 | |        Client App          |<-------------------->|  Authz   |
 | |                            |  |                   |  Server  |
 | +----------------------------+  |                   |          |
 |   ^ (1)      |  ^          |    |                   +----------+
 |   | read     |  | (3)      |    | 
 |   | bound    |  | token    |    |               
 |   | user     |  | response |    |               
 |   |          |  |          |    |          
 |   |    (2)   |  |    (5)   |    |               
 |   |    load  |  |    save  |    |               
 |   |    token |  |    bound |    |                
 |   v          v  |    user  v    |                
 | +----------------------------+  |                   +----------+
 | |                            |  |   (2.1) request   |          |
 | |       IDP IFrame           |  |   access token    |  IDP     |
 | |                            |<-------------------->|  Server  |
 | +----------------------------+  |                   |          |
 |                                 |                   +----------+
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
</pre>
<p/>
<p id="rfc.section.1.4.p.2">Above figure illustrates the interaction of the client app with the IDP IFrame to get a token response or achieve authorization when needed.  Below are the detailed description for each steps.  </p>
<p/>

<dl>
  <dt>1)</dt>
  <dd style="margin-left: 8">On RP page loaded, the client SHOULD send getSessionSelector RPC to read the login hint of the bound user for current RP.  If there is a bound user, go to step 2. Otherwise, go to step 6 to select one.  </dd>
  <dt>2)</dt>
  <dd style="margin-left: 8">The client sends getTokenResponse to load a TokenResponse for the bound user.  The IDP IFrame SHOULD check the sessionStorage-based cache firstly.  If no cached token response found, the IDP IFrame will connect to IDP server to issue a new one, which SHOULD be cached for reuse before returning to RP.  To check whether a cached token response is suitable for current request, the requested client, user, scopes, response types, expires date MUST be taken into account.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">If bound user doesn't have an active session in the IDP side, an user_logged_out error MUST be returned.  If permission from end user is needed, an immediate_failed error MUST be returned.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">It is the client's responsibility to send another getTokenResponse RPC to renew an expiring access token.  </dd>
  <dt>3)</dt>
  <dd style="margin-left: 8">If immediate_failed error returns, client SHOULD direct end user to the authorization endpoint to grant the permission.  An authorization URL should be created whose response_type MUST contain permission type.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">The permission response type, which is defined in this specification, allows authorization endpoint support both legacy and new implicit flow at the same time.  The information returned in the response are different.  Most obviously, the access token MUST NOT return in permission response type, whereas the login hint doesn't be returned for the legacy token response type.  </dd>
  <dt>4)</dt>
  <dd style="margin-left: 8">After receives a permission request, IDP server shows the approval page to end user.  If user approves the request, the login hint of the bound user MUST be returned.  If user denies the request, an access_denied error MUST be returned.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">In popup mode, a redirect_uri with storagerelay scheme SHOULD be used.  The response will be relayed to the IDP IFrame in the main window, then it will be sent to target client as an AuthResult event.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">In full page redirection mode, the response SHOULD be sent via HTTP redirection.  Clients MUST read the authorization response from the URL fragment.  </dd>
  <dt>5)</dt>
  <dd style="margin-left: 8">On receiving an approval authorization response, the client SHOULD store the returned login hint into the RP session selector in the IDP IFrame.  The change to the RP session selector will trigger SessionSelectorChanged events on all tabs in current RP domain, which will cause the clients on all these tabs reload access tokens for the new bound user immediately.  </dd>
  <dt>6)</dt>
  <dd style="margin-left: 8">There are two ways to switch bound user, or set the initial bound user: IDP side selection; and RP side selection.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">For IDP side selection, end user is directed to IDP Authorization endpoint with a permission request, then the returned login hint will be used as the new bound user.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">For RP side selection, client first sends a listIdpSessions RPC to IDP IFrame. The IDP IFrame SHALL enumerate all active IDP sessions in the response.  For sessions that have approved the client for all the requested scopes, IDP IFrame SHOULD return its login hint.  Then the RP session selection can be switched in RP side by storing a new login hint into the RP session selector.  </dd>
  <dt>7)</dt>
  <dd style="margin-left: 8">RP side logout is also supported by the disabled attribute.  Clients MUST NOT automatically get access token or redirect to select a session if disabled attribute is true.  </dd>
  <dt>8)</dt>
  <dd style="margin-left: 8">Clients can send revoke RPC to IDP IFrame to revoke all the scopes granted to current client.  Clients MUST have a valid access token to perform this operation.  </dd>
  <dt>9)</dt>
  <dd style="margin-left: 8">Clients SHOULD use storagerelay scheme redirect_uri when requesting a code in popup mode.  The response will be relayed to the IDP IFrame in the main window, then it will be sent to target client as an AuthResult event.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">This allows RP to get authorization code without the need to add an new endpoint to receive the response.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.1.5"><a href="#rfc.section.1.5">1.5.</a> <a href="#login_hint" id="login_hint">Login Hint</a></h1>
<p id="rfc.section.1.5.p.1">Login hint is an opaque string used to keep track of the bound user in RP side.  For better privacy, IDP should use domain-specific login hint.  </p>
<p id="rfc.section.1.5.p.2">Below is the life cycle for a login hint.  </p>
<p/>

<dl>
  <dt>1)</dt>
  <dd style="margin-left: 8">Login hint is returned in listIdpSessions RPC, or in the authorization response from IDP authorization endpoint for a request with permission response type.  </dd>
  <dt>2)</dt>
  <dd style="margin-left: 8">Client saves it into Session Selector by setSessionSelector RPC.  Other clients will get notified by a SessionSelectorChanged event, which contains the new login hint.  </dd>
  <dt>3)</dt>
  <dd style="margin-left: 8">The login hint will be persistent in the web storage of the IDP IFrame until end user changes it.  </dd>
  <dt>4)</dt>
  <dd style="margin-left: 8">On page reload, clients must get bound user firstly from Session Selector by getSessionSelector RPC.  </dd>
  <dt>5)</dt>
  <dd style="margin-left: 8">A valid login hint MUST be provided to get tokens by getTokenResponse RPC.  The IDP IFrame will only return tokens for the user specified by the login hint, and only when the user has an active session in the IDP side.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.1.6"><a href="#rfc.section.1.6">1.6.</a> <a href="#session_selector" id="session_selector">Session Selector</a></h1>
<p id="rfc.section.1.6.p.1">Session selector is a private storage provided by IDP IFrame for an RP.  </p>
<p id="rfc.section.1.6.p.2">SessionSelectorConfig is a data structure that clients use to designate which session selector should be used.  </p>
<p id="rfc.section.1.6.p.3">Different SessionSelectorConfig values will be mapped to different session selectors, which are totally invisible to each other.  For example, two SessionSelectorConfig with same domain but different crossSubDomains values will be mapped into two different storage items, and thus are totally separated session selectors.  </p>
<p id="rfc.section.1.6.p.4">Different container pages share the same session selection and session state only when their SessionSelectorConfig values are exactly same, in other words, when they designate the same session selector.  </p>
<p id="rfc.section.1.6.p.5">Below is an example of SessionSelectorConfig.  </p>
<pre>
{
    "domain":"http://examplerp.com",
    "crossSubDomains":true
}
</pre>
<p/>
<p/>

<dl>
  <dt>domain</dt>
  <dd style="margin-left: 8"><br/> the top RP domain that the bound user to be shared. If crossSubDomains is false, only clients in the domain can access the session selector.  </dd>
  <dt>crossSubDomains</dt>
  <dd style="margin-left: 8"><br/> whether the bound user is shared by sub domains.  </dd>
  <dt>policy</dt>
  <dd style="margin-left: 8"><br/> (Reserved for future use.) Domain access policy, which controls whether a subdomain has access to a session selector defined under parent domain. Current only default policy is defined.  </dd>
  <dt>id</dt>
  <dd style="margin-left: 8"><br/> (Reserved for future use.) The ID of the session selector, which allows an IDP supports multiple session selectors at the same time. For example, 'test' and 'prod'.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.1.6.1"><a href="#rfc.section.1.6.1">1.6.1.</a> <a href="#default_domain_access_policy" id="default_domain_access_policy">Default Domain Access Policy</a></h1>
<p id="rfc.section.1.6.1.p.1">Currently only the default policy is defined. For default policy, below rules apply.  </p>
<p/>

<ul>
  <li>An https origin can access session selector in http domain.  For example, https://example.com pages can access session selector defined for domain http://example.com.  </li>
  <li>An http origin cannot access session selector in https domain.  For example, http://example.com pages cannot access session selector defined for domain https://example.com.  </li>
  <li>A sub domain in standard port can access parent domain.  For example, http://www.example.com can access http://example.com.  </li>
  <li>An origin in non-standard port cannot access an origin with same hostname but different port number.  For example, http://example.com:8080 and http://example.com are invisible to each other.  </li>
</ul>

<p> </p>
<p id="rfc.section.1.6.1.p.3">As a result, when crossSubDomains is true: </p>
<p/>

<ul>
  <li>if domain is http://example.com, the session selector is visible to both http://example.com and https://example.com doamins and all their sub domains in standard ports.  </li>
  <li>if domain is https://example.com, the session selector is only visible to https://example.com domain and all its sub domains in standard ports.  </li>
  <li>if domain http://example.com:8080, the session selector is only visible to http://example.com:8080 itself. It is not visible to https://example.com:8080, or http://www.example.com:8080.  </li>
</ul>

<p> </p>
<p id="rfc.section.1.6.1.p.5">Additional policies may be defined in the future to allow more flexibility.  </p>
<h1 id="rfc.section.1.7"><a href="#rfc.section.1.7">1.7.</a> <a href="#storagerelay_scheme_uri" id="storagerelay_scheme_uri">storagerelay Scheme URI</a></h1>
<p id="rfc.section.1.7.p.1">HTML5 localStorage can be used to send messages across tabs.  If an item in localStorage is changed by one tab, other tabs will receive a Storage Event.  This feature can be used to relay authorization response from popup window to the main window.  </p>
<p id="rfc.section.1.7.p.2">Below is the steps to relay authorization response via web storage.  </p>
<p/>

<ul>
  <li>The IDP IFrame in the main window will listen on storage events.  </li>
  <li>The client creates a storagerelay URI, which contains RP origin and a request ID.  Together with the client ID, it will be used to generate a localStorage key in the authorization endpoint.  </li>
  <li>The client creates an auth URL with the stoagerealy URI as the redirect_uri.  Suppose a popup window with the auth URL is opened.  </li>
  <li>In the popup window, after an authorization decision is made, the authorization response is wrapped into a string and written into localStorage under the key that is generated from the storagerelay URI.  Then the item should be deleted after a small delay. After that, the popup window can be closed.  </li>
  <li>After receiving a storage event, the IDP IFrame will parse the client ID and origin from the 'key' field.  If this is the right target, the response will be parsed from the 'newValue' field.  An AuthResult event is created to relay the response from the IDP IFrame to container page.  To differentiate the event generated when deleting the item, storage event with empty 'newValue' will be ignored.  </li>
  <li>Once receiving an AuthResult event, the container page should check the request ID to make sure the request is originated from it.  </li>
</ul>

<p> </p>
<h1 id="rfc.section.1.8"><a href="#rfc.section.1.8">1.8.</a> <a href="#parameters_naming_rules" id="parameters_naming_rules">Parameters Naming Rules</a></h1>
<p id="rfc.section.1.8.p.1">In the essential, this specification defines some data structures that can be used by JavaScript codes to exchange message across iframes.  Traditionally, JavaScript codes should use camelcase variable and field names, like clientId, rpcToken, etc.  </p>
<p id="rfc.section.1.8.p.2">Unfortunately, RFC 6749 already defines some OAuth 2.0 parameter names in underbar format, based on the assumption that these parameters are URL parameters.  For example, client_id, response_type, etc. When communicating with authorization endpoints, we must use underbar names to be consistent with RFC 6749.  </p>
<p id="rfc.section.1.8.p.3">As a result, both camelcase and underbase names are used in this specification.  Below rules apply when deciding which format should be used.  </p>
<p/>

<ul>
  <li>The request and response parameter names of the authorization endpoint must be underbar names (to follow RFC 6749).  </li>
  <li>The params.request of getTokenResponse RPC is used to hold parameters that are expected to construct the authorization URL.  The parameters inside params.request should be underbar names.  </li>
  <li>Some RPC responses are generated by IDP server side endpoints, and expected to be consumed by clients.  It seems insensible to translate them from underbar names to camelcase names.  In this case, the underbar names are directly exposed to clients.  The examples are the response of getTokenResponse RPC, listIdpSessions RPC, revoke RPC.  </li>
  <li>Same case for the authResult field of AuthResult Event, which holds authorization response.  </li>
  <li>For all other cases, the camelcase names should be used.  </li>
</ul>

<p> </p>
<h1 id="rfc.section.2"><a href="#rfc.section.2">2.</a> <a href="#idp_iframe" id="idp_iframe">IDP IFrame</a></h1>
<p id="rfc.section.2.p.1">IDP IFrame is a hidden IFrame provided by IDP, which can be embedded into a container page in third party domain, and provides OAuth 2.0 token and session services on behalf of the IDP for the JavaScript clients that are running in the container page.  </p>
<p id="rfc.section.2.p.2">IDP IFrame should only contains HTML and static JavaScript codes. IDP IFrame JavaScript codes have below dependencies: </p>
<p/>

<dl>
  <dt></dt>
  <dd style="margin-left: 8">HTML5 Web Storage: persist session selector; cache token responses, etc.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">HTML5 postMessage: communicates with container page.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">Cookies: Monitor IDP Session state change.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">XMLHttpRequest: communicates with IDP server side endpoints (to issue a token, enumerate session state, etc.).  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.2.1"><a href="#rfc.section.2.1">2.1.</a> <a href="#embed_idp_iframe" id="embed_idp_iframe">Embed IDP IFrame Into A Container Page</a></h1>
<p id="rfc.section.2.1.p.1">IDP IFrame SHOULD NOT set x-frame-options headers.  </p>
<p id="rfc.section.2.1.p.2">Since the IDP IFrame will be loaded on each container page reload, it is vital important to set cache-control: public header to avoid the huge traffic to load the IDP IFrame itself.  </p>
<p id="rfc.section.2.1.p.3">Below is a sample code in a container page to embed an IDP IFrame.  </p>
<pre>
  <iframe id="iframe_id"
    style="position: absolute; width: 1px; height: 1px; left: -9999px;"
    sandbox="allow-scripts allow-same-origin"
    src="https://idp.com/ifr#origin=http://rp.com&rpcToken=8462679">
</pre>
<p/>
<p id="rfc.section.2.1.p.5">The iframe has below attributes: </p>
<p/>

<dl>
  <dt>id</dt>
  <dd style="margin-left: 8"><br/> Optional. A unique ID for this iframe.  </dd>
  <dt>style</dt>
  <dd style="margin-left: 8"><br/> CSS code to make the iframe hidden.  </dd>
  <dt>sandbox</dt>
  <dd style="margin-left: 8"><br/> Enable JavaScript and web storage access.  </dd>
  <dt>src</dt>
  <dd style="margin-left: 8"><br/> The URL and initialization parameters for the IDP IFrame. Some initialization parameters can be passed to IDP IFrame in the URL fragment.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.2.1.1"><a href="#rfc.section.2.1.1">2.1.1.</a> <a href="#idp_iframe_init_params" id="idp_iframe_init_params">IDP IFrame Initialization Parameters</a></h1>
<p id="rfc.section.2.1.1.p.1">A container page MUST set initialization parameters for the IDP IFrame in the URL fragment.  </p>
<pre>
  https://idp.com/iframe#origin=https://rp.com&rpcToken=84462679
</pre>
<p/>
<p id="rfc.section.2.1.1.p.3">Below initialization parameters are defined.  </p>
<p/>

<dl>
  <dt>origin</dt>
  <dd style="margin-left: 8"><br/> Required. The origin of the container page. This is the only origin that the IDP IFrame will receive message from and send message to.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Required. A random secret is shared between the IDP IFrame and the container page. For each message between them, the RPC token must be included.  </dd>
  <dt>clearCache</dt>
  <dd style="margin-left: 8"><br/> Optional. A boolean value (0 or 1) to indicate whether to clear the cache for current origin in the IDP IFrame.  If clearCache=1 included, when initializing the IDP IFrame, all cached data for current origin will be cleared.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.2.2"><a href="#rfc.section.2.2">2.2.</a> <a href="#provisioning" id="provisioning">Provisioning</a></h1>
<p id="rfc.section.2.2.p.1">The communication between the container page and the IDP IFrame is based on HTML5 postMessage.  The message handler on the receiving side should be ready before the sending side can send out a message.  </p>
<p id="rfc.section.2.2.p.2">Below rules are defined for this.  </p>
<p/>

<dl>
  <dt>1)</dt>
  <dd style="margin-left: 8">The container page MUST make its message handler ready before embedding the IDP IFrame.  </dd>
  <dt>2)</dt>
  <dd style="margin-left: 8">Once loaded, the IDP IFrame MUST get the client origin and RPC token from the URL fragment, and make its message handler ready.  For security reasons, only that client origin is allowed to communicate with the IDP IFrame loaded.  </dd>
  <dt>3)</dt>
  <dd style="margin-left: 8">The IDP IFrame MUST send an idpReady event to the client origin.  </dd>
  <dt>4)</dt>
  <dd style="margin-left: 8">Only after the idpReady event is received can the container page send messages to the IDP IFrame.  </dd>
</dl>

<p> </p>
<p id="rfc.section.2.2.p.4">Below is an example idpReady event from the IDP IFrame.  </p>
<pre>
  {
    "method":"fireIdpEvent",
    "params":{"type":"idpReady"},
    "rpcToken":"12345678"
  }
</pre>
<p/>
<p id="rfc.section.2.2.p.6">Below initialization parameters are defined.  </p>
<p/>

<dl>
  <dt>method</dt>
  <dd style="margin-left: 8"><br/> The message type. For all IDP events, the method is 'fireIdpEvent'.  </dd>
  <dt>params.type</dt>
  <dd style="margin-left: 8"><br/> The event type.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Shared RPC token.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.2.3"><a href="#rfc.section.2.3">2.3.</a> <a href="#idp_iframe_rpcs" id="idp_iframe_rpcs">RPCs</a></h1>
<p id="rfc.section.2.3.p.1">After the IDP IFrame provisioning, the container page can send RPC requests to IDP IFrame, for example, to get an OAuth 2.0 access token, to list all IDP sessions, etc.  </p>
<p id="rfc.section.2.3.p.2">On receiving a request, the IDP IFrame MUST first check its validity, then process it by looking up the cache or sending AJAX requests to server side endpoints.  If there is an id field in the RPC request, the IDP IFrame MUST send back a RPC response.  </p>
<p id="rfc.section.2.3.p.3">The RPC requests and responses will be serialized to strings, and sent via HTML5 postMessage.  </p>
<p id="rfc.section.2.3.p.4">IDP IFrame MUST support below RPCs.  </p>
<p/>

<dl>
  <dt>monitorClient</dt>
  <dd style="margin-left: 8"><br/> Registers a client to the IDP IFrame, so that IDP IFrame knows that the target client is running on the container page.  </dd>
  <dt>getSessionSelector</dt>
  <dd style="margin-left: 8"><br/> Gets the persistent login hint of bound user and the disabled state in the session selector of current RP.  </dd>
  <dt>setSessionSelector</dt>
  <dd style="margin-left: 8"><br/> Changes the bound user or the disabled state in the session selector of current RP.  </dd>
  <dt>getTokenResponse</dt>
  <dd style="margin-left: 8"><br/> Loads access token or ID token from the IDP IFrame. The tokens MAY be loaded from the cache in the IDP IFrame.  </dd>
  <dt>listIdpSessions</dt>
  <dd style="margin-left: 8"><br/> Lists all IDP sessions. The response MAY be loaded from the cache in the IDP IFrame.  </dd>
  <dt>revoke</dt>
  <dd style="margin-left: 8"><br/> Revokes all granted permissions for the client.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.2.3.1"><a href="#rfc.section.2.3.1">2.3.1.</a> <a href="#rpc_monitorClient" id="rpc_monitorClient">monitorClient</a></h1>
<p id="rfc.section.2.3.1.p.1">Registers a client to the IDP IFrame, so that IDP IFrame knows that the target client is running on the container page.  The container page can receive IDP IFrame Events for a client only after the client is registered.  </p>
<p id="rfc.section.2.3.1.p.2">Below is an example monitorClient RPC request.  </p>
<pre>
  {
    "method":"monitorClient",
    "params":{
        "clientId":"483367325260.googleusercontent.com"
    },
    "id":"205-335666.4125872184",
    "rpcToken":"12345678"
  }
</pre>
<p/>
<p/>

<dl>
  <dt>method</dt>
  <dd style="margin-left: 8"><br/> The RPC type.  </dd>
  <dt>params.clientId</dt>
  <dd style="margin-left: 8"><br/> The ID of the client to be registered.  </dd>
  <dt>id</dt>
  <dd style="margin-left: 8"><br/> Optional. The ID of the request.  If present, the IDP IFrame must return a response as defined below.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Shared RPC token.  </dd>
</dl>

<p> </p>
<p id="rfc.section.2.3.1.p.5">Below is an example monitorClient RPC response.  </p>
<pre>
  {
    "id":"205-335666.4125872184",
    "result":true,
    "rpcToken":"12345678"
  }
</pre>
<p/>
<p/>
<p/>

<dl>
  <dt>result</dt>
  <dd style="margin-left: 8"><br/> A boolean value to indicate whether the client is registered or not.  </dd>
  <dt>id</dt>
  <dd style="margin-left: 8"><br/> The ID of the corresponding RPC request.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Shared RPC token.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.2.3.2"><a href="#rfc.section.2.3.2">2.3.2.</a> <a href="#rpc_getSessionSelector" id="rpc_getSessionSelector">getSessionSelector</a></h1>
<p id="rfc.section.2.3.2.p.1">Gets the persistent login hint of bound user and the disabled state in the session selector of current RP.  </p>
<p id="rfc.section.2.3.2.p.2">Below is an example getSessionSelector RPC request.  </p>
<pre>
  {
    "method":"getSessionSelector",
    "params":{
        "crossSubDomains":true,
        "domain":"https://gapi-idp.appspot.com"
    },
    "id":"505-382131.15223600523",
    "rpcToken":"12345678"
  }
</pre>
<p/>
<p/>

<dl>
  <dt>method</dt>
  <dd style="margin-left: 8"><br/> The RPC type.  </dd>
  <dt>params.crossSubDomains</dt>
  <dd style="margin-left: 8"><br/> Session selector config field 'crossSubDomains'.  </dd>
  <dt>params.domain</dt>
  <dd style="margin-left: 8"><br/> Session selector config field 'domain'.  </dd>
  <dt>id</dt>
  <dd style="margin-left: 8"><br/> Optional. The ID of the request.  If present, the IDP IFrame must return a response as defined below.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Shared RPC Token.  </dd>
</dl>

<p> </p>
<p id="rfc.section.2.3.2.p.5">Below is an example getSessionSelector RPC response.  </p>
<pre>
  {
    "id":"505-382131.15223600523",
    "result":{
        "hint":"AJMrCA...",
        "disabled":false
    },
    "rpcToken":"12345678"
  }
</pre>
<p/>
<p id="rfc.section.2.3.2.p.7">Below is an example getSessionSelector RPC response.  </p>
<p/>

<dl>
  <dt>result.hint</dt>
  <dd style="margin-left: 8"><br/> The login hint of the bound user.  </dd>
  <dt>result.disabled</dt>
  <dd style="margin-left: 8"><br/> A boolean value to indicate whether user is RP side logged out. Value true means logged out.  </dd>
  <dt>id</dt>
  <dd style="margin-left: 8"><br/> The ID of the corresponding RPC request.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Shared RPC Token.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.2.3.3"><a href="#rfc.section.2.3.3">2.3.3.</a> <a href="#rpc_setSessionSelector" id="rpc_setSessionSelector">setSessionSelector</a></h1>
<p id="rfc.section.2.3.3.p.1">Changes the bound user or the disabled state in the session selector of current RP.  </p>
<p id="rfc.section.2.3.3.p.2">Below is an example setSessionSelector RPC request.  </p>
<pre>
  {
    "method":"setSessionSelector",
    "params":
        "crossSubDomains":true,
        "domain":"https://gapi-idp.appspot.com",
        "hint":"AJMrCA...",
        "disabled":false
    },
    "id":"163-974071.9209347457",
    "rpcToken":"12345678"
  }
</pre>
<p/>
<p/>

<dl>
  <dt>method</dt>
  <dd style="margin-left: 8"><br/> The RPC type.  </dd>
  <dt>params.crossSubDomains</dt>
  <dd style="margin-left: 8"><br/> Session selector config field 'crossSubDomains'.  </dd>
  <dt>params.domain</dt>
  <dd style="margin-left: 8"><br/> Session selector config field 'domain'.  </dd>
  <dt>params.hint</dt>
  <dd style="margin-left: 8"><br/> The login hint of the bound user to be set.  </dd>
  <dt>params.disabled</dt>
  <dd style="margin-left: 8"><br/> A boolean value to indicate whether user is RP side logged out.  Value true means logged-out.  </dd>
  <dt>id</dt>
  <dd style="margin-left: 8"><br/> Optional. The ID of the request.  If present, the IDP IFrame must return a response as defined below.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Shared RPC Token.  </dd>
</dl>

<p> </p>
<p id="rfc.section.2.3.3.p.5">Below is an example setSessionSelector RPC response.  </p>
<pre>
  {
    "id":"163-974071.9209347457",
    "result":true,
    "rpcToken":"12345678"
  }
</pre>
<p/>
<p/>

<dl>
  <dt>result</dt>
  <dd style="margin-left: 8"><br/> A boolean value to indicate whether the session selector is updated successfully.  </dd>
  <dt>id</dt>
  <dd style="margin-left: 8"><br/> The ID of the corresponding RPC request.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Shared RPC Token.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.2.3.4"><a href="#rfc.section.2.3.4">2.3.4.</a> <a href="#rpc_getTokenResponse" id="rpc_getTokenResponse">getTokenResponse</a></h1>
<p id="rfc.section.2.3.4.p.1">Loads access token or ID token from the IDP IFrame. The tokens may be loaded from the cache in the IDP IFrame.  </p>
<p id="rfc.section.2.3.4.p.2">Below is an example getTokenResponse RPC request.  </p>
<pre>
  {
    "method":"getTokenResponse",
    "params":{
        "clientId":"48336732526.apps.googleusercontent.com",
        "loginHint":"AJMrCA...",
        "sessionSelector":{
            "domain":"http://examplerp.com"
        },
        "request":{
            "response_type":"token id_token",
            "scope":"profile email"
        },
        "forceRefresh":false
    },
    "id":"205-791673.6432735061",
    "rpcToken":"12345678"
  }
</pre>
<p/>
<p/>

<dl>
  <dt>method</dt>
  <dd style="margin-left: 8"><br/> The RPC type.  </dd>
  <dt>params.clientId</dt>
  <dd style="margin-left: 8"><br/> The ID of the client.  </dd>
  <dt>params.loginHint</dt>
  <dd style="margin-left: 8"><br/> The login hint of the bound user.  </dd>
  <dt>params.sessionSelector.domain</dt>
  <dd style="margin-left: 8"><br/> The RP session selector domain, which should be used when generating domain specific login hint.  </dd>
  <dt>params.request.response_type</dt>
  <dd style="margin-left: 8"><br/> OAuth 2.0 request parameter response_type.  Valid values are 'token', 'id_token', or 'token id_token'.  </dd>
  <dt>params.request.scope</dt>
  <dd style="margin-left: 8"><br/> OAuth 2.0 request parameter scope.  </dd>
  <dt>params.forceRefresh</dt>
  <dd style="margin-left: 8"><br/> Whether to ignore the cache, and get a new token response from IDP server.  </dd>
  <dt>id</dt>
  <dd style="margin-left: 8"><br/> Optional. The ID of the request.  If present, the IDP IFrame must return a response as defined below.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Shared RPC Token.  </dd>
</dl>

<p> </p>
<p id="rfc.section.2.3.4.p.5">Below is an example getTokenResponse RPC response.  </p>
<pre>
  {
    "id":"205-791673.6432735061",
    "result":{
        "token_type":"Bearer",
        "access_token":"ya29.9A...",
        "scope":"openid email",
        "login_hint":"AJMrCA...",
        "id_token":"eUxA....",
        "session_state":{
            "extraQueryParams":{
               "authuser":"0"
            }
        },
        "first_issued_at":1420598000330,
        "expires_at":1420601600330
        "expires_in":3600,
    },
    "rpcToken":"12345678"
  }
</pre>
<p/>
<p/>
<p/>

<dl>
  <dt>result.token_type</dt>
  <dd style="margin-left: 8"><br/> OAuth 2.0 response parameter token_type.  </dd>
  <dt>result.access_token</dt>
  <dd style="margin-left: 8"><br/> OAuth 2.0 response parameter access_token.  This parameter is always returned.  </dd>
  <dt>result.id_token</dt>
  <dd style="margin-left: 8"><br/> OpenID connect response parameter id_token.  Returned only when 'id_token' is requested.  </dd>
  <dt>params.login_hint</dt>
  <dd style="margin-left: 8"><br/> The login hint of the user who issues the tokens.  </dd>
  <dt>params.scope</dt>
  <dd style="margin-left: 8"><br/> The granted scopes for the tokens.  This may return different value to the requested scope due to two reasons: <dl><dt>1)</dt><dd style="margin-left: 8">IDP may turn the scope alias into a normalized form.  </dd><dt>2)</dt><dd style="margin-left: 8">To support incremental auth, IDP may include previously granted scopes.  </dd></dl><p> </p></dd>
  <dt>params.session_state</dt>
  <dd style="margin-left: 8"><br/> The session selection information for current session.  Can be used to select the session in the IDP.  </dd>
  <dt>params.session_state.extraQueryParams</dt>
  <dd style="margin-left: 8"><br/> Extra query parameters used to select the user session in IDP side.  The parameters inside extraQueryParams (say, authuser) are IDP specific.  The client doesn't need to know the meaning of them. When generating authorization URL, these parameters will be appended to the URL query.  </dd>
  <dt>id</dt>
  <dd style="margin-left: 8"><br/> The ID of the corresponding RPC request.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Shared RPC Token.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.2.3.5"><a href="#rfc.section.2.3.5">2.3.5.</a> <a href="#rpc_listIdpSessions" id="rpc_listIdpSessions">listIdpSessions</a></h1>
<p id="rfc.section.2.3.5.p.1">Enumerates all IDP sessions. The response may be loaded from the cache in the IDP IFrame.  </p>
<p id="rfc.section.2.3.5.p.2">If a session user has already approved all requested scopes, the login hint will be included in the response.  </p>
<p id="rfc.section.2.3.5.p.3">If a session user has already approved email-related scope, the IDP is RECOMMENDED to return the email of the session user.  </p>
<p id="rfc.section.2.3.5.p.4">If a session user has already approved profile-related scope, the IDP is RECOMMENDED to return the displayName and photoUrl of the session user.  </p>
<p id="rfc.section.2.3.5.p.5">The email, displayName, and photoUrl allow RP to render a user friendly session selection UI on the RP side.  </p>
<p id="rfc.section.2.3.5.p.6">Below is an example listIdpSessions RPC request.  </p>
<pre>
  {
    "method":"listIdpSessions",
    "params":{
        "clientId":"4833673.apps.googleusercontent.com",
        "sessionSelector":{
            "domain":"http://examplerp.com"
        },
        "request":{
            "scope":"profile email"
        },
        "forceRefresh":false
    },
    "id":"599-211931.20572639475"
    "rpcToken":"12345678"
  }
</pre>
<p/>
<p/>
<p/>

<dl>
  <dt>method</dt>
  <dd style="margin-left: 8"><br/> The RPC type.  </dd>
  <dt>params.clientId</dt>
  <dd style="margin-left: 8"><br/> The ID of the client to be registered.  </dd>
  <dt>params.sessionSelector.domain</dt>
  <dd style="margin-left: 8"><br/> The RP session selector domain, which should be used when generating domain specific login hint.  </dd>
  <dt>params.request.scope</dt>
  <dd style="margin-left: 8"><br/> The OAuth 2.0 request parameter scope.  </dd>
  <dt>params.forceRefresh</dt>
  <dd style="margin-left: 8"><br/> Whether to ignore the cache, and refresh the session states from IDP server.  </dd>
  <dt>id</dt>
  <dd style="margin-left: 8"><br/> Optional. The ID of the request.  If present, the IDP IFrame must return a response as defined below.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Shared RPC Token.  </dd>
</dl>

<p> </p>
<p id="rfc.section.2.3.5.p.10">Below is an example listIdpSessions RPC response.  </p>
<pre>
  {
    "id":"599-211931.20572639475",
    "result":{
        "sessions":[{
          "login_hint":"AJMrCA...",
          "email":"test@gmail.com",
          "displayName":"James Zhao",
          "photoUrl":"https://someUrl",
          "session_state":{
              "extraQueryParams":{"authuser":"0"}
          }
        },{
          "session_state":{
              "extraQueryParams":{"authuser":"1"}
          }
        }],
       "first_issued_at":1420605596916,
       "expires_at":1420609196916,
       "scope":"openid email"
    },
    "rpcToken":"12345678"
  }
</pre>
<p/>
<p/>

<dl>
  <dt>result.sessions</dt>
  <dd style="margin-left: 8"><br/> An array of session meta information. Each element corresponds to one IDP session.  </dd>
  <dt>result.sessions[i].login_hint</dt>
  <dd style="margin-left: 8"><br/> The login hint of the session user.  Returned only when the session user has granted all requested scopes for the client.  </dd>
  <dt>result.sessions[i].email</dt>
  <dd style="margin-left: 8"><br/> The email of the session user.  Returned only when the session user has granted email-related scope for the client.  </dd>
  <dt>result.sessions[i].displayName</dt>
  <dd style="margin-left: 8"><br/> The login hint of the session user.  Returned only when the session user has granted profile-related for the client.  </dd>
  <dt>result.sessions[i].photoUrl</dt>
  <dd style="margin-left: 8"><br/> The login hint of the session user.  Returned only when the session user has granted profile-related for the client.  </dd>
  <dt>result.sessions[i].session_state</dt>
  <dd style="margin-left: 8"><br/> session selection information. Can be used to select the session in the IDP.  </dd>
  <dt>params.sessions[i].session_state.extraQueryParams</dt>
  <dd style="margin-left: 8"><br/> Extra query parameters used to select the user session in IDP side.  The parameters inside extraQueryParams (say, authuser) are IDP specific.  The client doesn't need to know the meaning of them.  When generating authorization URL, these parameters will be appended to the URL query.  </dd>
  <dt>id</dt>
  <dd style="margin-left: 8"><br/> The ID of the corresponding RPC request.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Shared RPC Token.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.2.3.6"><a href="#rfc.section.2.3.6">2.3.6.</a> <a href="#rpc_revoke" id="rpc_revoke">revoke</a></h1>
<p id="rfc.section.2.3.6.p.1">Revokes all granted permissions for the client.  </p>
<p id="rfc.section.2.3.6.p.2">Below is an example revoke RPC request.  </p>
<pre>
  {
    "method":"revoke",
    "params":{
        "clientId":"4833673.apps.googleusercontent.com"
        "token":"ya29.9A...",
    },
    "id":"993-345439.5964317359"
    "rpcToken":"12345678"
  }
</pre>
<p/>
<p/>

<dl>
  <dt>method</dt>
  <dd style="margin-left: 8"><br/> The RPC type.  </dd>
  <dt>params.clientId</dt>
  <dd style="margin-left: 8"><br/> The ID of the client to be registered.  </dd>
  <dt>params.token</dt>
  <dd style="margin-left: 8"><br/> The access token for the client.  </dd>
  <dt>id</dt>
  <dd style="margin-left: 8"><br/> Optional. The ID of the request.  If present, the IDP IFrame must return a response as defined below.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Shared RPC Token.  </dd>
</dl>

<p> </p>
<p id="rfc.section.2.3.6.p.5">Below is an example revoke RPC response.  </p>
<pre>
  {
    "id":"993-345439.5964317359",
    "result":true,
    "rpcToken":"12345678"
  }
</pre>
<p/>
<p/>
<p/>

<dl>
  <dt>result</dt>
  <dd style="margin-left: 8"><br/> A boolean value to indicate whether the revocation is successful.  </dd>
  <dt>id</dt>
  <dd style="margin-left: 8"><br/> The ID of the corresponding RPC request.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Shared RPC Token.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.2.4"><a href="#rfc.section.2.4">2.4.</a> <a href="#idp_iframe_events" id="idp_iframe_events">Events</a></h1>
<p id="rfc.section.2.4.p.1">When something changes in the IDP IFrame, the IDP IFrame can fire Events to notify the client.  </p>
<p id="rfc.section.2.4.p.2">IDP IFrame will fire below events.  </p>
<p/>

<dl>
  <dt>SessionStateChanged</dt>
  <dd style="margin-left: 8"><br/> The IDP session state has changed.  </dd>
  <dt>SessionSelectorChange</dt>
  <dd style="margin-left: 8"><br/> The session selection or RP logout state has changed.  </dd>
  <dt>AuthResult</dt>
  <dd style="margin-left: 8"><br/> An authorization response is returned.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.2.4.1"><a href="#rfc.section.2.4.1">2.4.1.</a> <a href="#event_sessionStateChanged" id="event_sessionStateChanged">SessionStateChanged</a></h1>
<p id="rfc.section.2.4.1.p.1">The IDP IFrame will monitor the IDP session cookie.  If it changes, the IDP IFrame will connect IDP server to refresh the session state.  If the login state for the bound user changes, a SessionStateChanged event will be fired to notify the client in the container page.  </p>
<p id="rfc.section.2.4.1.p.2">Below is an example SessionStateChanged event.  </p>
<pre>
  {
    "method":"fireIdpEvent",
    "params":{
        "type":"sessionStateChanged",
        "clientId":"685319905637.apps.googleusercontent.com",
        "user":"AOu8..."
        "sessionState":{
            "extraQueryParams":{"authuser":"0"}
        }
    },
    "rpcToken":"12345678"
  }
</pre>
<p/>
<p/>

<dl>
  <dt>method</dt>
  <dd style="margin-left: 8"><br/> The message type. For all IDP events, the method is 'fireIdpEvent'.  </dd>
  <dt>params.type</dt>
  <dd style="margin-left: 8"><br/> The event type.  </dd>
  <dt>params.clientId</dt>
  <dd style="margin-left: 8"><br/> The ID of the client to be notified.  </dd>
  <dt>params.user</dt>
  <dd style="margin-left: 8"><br/> The login hint of the bound user.  </dd>
  <dt>params.sessionState</dt>
  <dd style="margin-left: 8"><br/> The session selection information.  If this field is missing, it means the user is logged out.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Shared RPC token.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.2.4.2"><a href="#rfc.section.2.4.2">2.4.2.</a> <a href="#event_sessionSelectorChanged" id="event_sessionSelectorChanged">SessionSelectorChanged</a></h1>
<p id="rfc.section.2.4.2.p.1">If the Session Selector value for current RP is changed by one client, the SessionSelectorChanged event will be fired to notify all clients to update.  </p>
<p id="rfc.section.2.4.2.p.2">There are two types of changes.  </p>

<ul>
  <li>Bound user changed.  </li>
  <li>RP side logout state (disabled state) changed.  </li>
</ul>

<p> </p>
<p id="rfc.section.2.4.2.p.3">Below is an example SessionSelectorChanged event.  </p>
<pre>
  {
    "method":"fireIdpEvent",
    "params":{
        "type":"sessionSelectorChanged",
        "newValue":{
            "hint":"AOEu8...",
            "disabled":false
        },
        "domain":"https://fi-idpiframe-app.appspot.com",
        "crossSubDomains":true
    },
    "rpcToken":"12345678"
  }
</pre>
<p/>
<p/>

<dl>
  <dt>method</dt>
  <dd style="margin-left: 8"><br/> The message type. For all IDP events, the method is 'fireIdpEvent'.  </dd>
  <dt>params.type</dt>
  <dd style="margin-left: 8"><br/> The event type.  </dd>
  <dt>params.newValue.hint</dt>
  <dd style="margin-left: 8"><br/> The login hint of the bound user.  </dd>
  <dt>params.newValue.disabled</dt>
  <dd style="margin-left: 8"><br/> The RP side logout state.  If user is logged out in the RP side, 'disabled' should be true.  </dd>
  <dt>params.domain</dt>
  <dd style="margin-left: 8"><br/> Session selector config field 'domain'.  </dd>
  <dt>params.crossSubDomains</dt>
  <dd style="margin-left: 8"><br/> Session selector config field 'crossSubDomains'.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Shared RPC token.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.2.4.3"><a href="#rfc.section.2.4.3">2.4.3.</a> <a href="#event_authResult" id="event_authResult">AuthResult</a></h1>
<p id="rfc.section.2.4.3.p.1">In popup mode, after an authorization decision is made on the IDP consent page in the popup window, the container page in the main window will receive an AuthResult event, which holds the authorization response.  </p>
<p id="rfc.section.2.4.3.p.2">Below is an example AuthResult event.  </p>
<pre>
  {
    "method":"fireIdpEvent",
    "params":{
        "type":"authResult",
        "clientId":"685319905637.apps.googleusercontent.com",
        "id":"auth273261",
        "authResult":{
           "login_hint":"AOHg..."
        }
     },
    "rpcToken":"12345678"
  }
</pre>
<p/>
<p/>

<dl>
  <dt>method</dt>
  <dd style="margin-left: 8"><br/> The message type. For all IDP events, the method is 'fireIdpEvent'.  </dd>
  <dt>params.type</dt>
  <dd style="margin-left: 8"><br/> The event type.  </dd>
  <dt>params.clientId</dt>
  <dd style="margin-left: 8"><br/> The target client ID.  </dd>
  <dt>params.id</dt>
  <dd style="margin-left: 8"><br/> The request ID.  </dd>
  <dt>params.authResult</dt>
  <dd style="margin-left: 8"><br/> The authorization response.  </dd>
  <dt>rpcToken</dt>
  <dd style="margin-left: 8"><br/> Shared RPC token.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.3"><a href="#rfc.section.3">3.</a> <a href="#authorization_endpoint" id="authorization_endpoint">Authorization Endpoint</a></h1>
<p id="rfc.section.3.p.1">To support the IDP IFrame based Implicit Flow, IDP need to make some changes to Authorization Endpoint.  </p>
<p/>

<ul>
  <li>Support permission response type.  </li>
  <li>Support storagerelay scheme URI.  </li>
</ul>

<p> </p>
<h1 id="rfc.section.3.1"><a href="#rfc.section.3.1">3.1.</a> <a href="#permission_response_type" id="permission_response_type">Permission Response Type</a></h1>
<p id="rfc.section.3.1.p.1">The permission response type, instead of the token response type, should be used in the authorization URL to request approval from end user for the IDP IFrame based implicit flow.  </p>
<p id="rfc.section.3.1.p.2">Below are the differences between them.  </p>
<p/>

<ul>
  <li>Access tokens will be returned for token response type, but not for permission response type.  </li>
  <li>Login hint for the approving user will be returned for permission response type, but not for token response type.  </li>
  <li>Client ID is also returned for permission response type, which makes it easy for a RP to use a shared endpoint to handle the redirection from multiples IDPs or for different clients.  </li>
</ul>

<p> </p>
<p id="rfc.section.3.1.p.4">The permission response type is used in below two scenarios.  </p>
<p/>

<ul>
  <li>Request permissions. Presents consent page to end user to grant (additional) permissions to the client.  </li>
  <li>Switch bound user. Allows end user to select a different session, thus changes the bound user.  </li>
</ul>

<p> </p>
<p id="rfc.section.3.1.p.6">The code and id_token response types can be used together with permission response type.  This allows the JavaScript clients to piggy-back authorization code and ID token for its server side when requesting permissions from authorization endpoint.  </p>
<p id="rfc.section.3.1.p.7">To make it clear, although the authorization code is returned from the IDP IFrame in an AuthResult event, it is issued in authorization endpoint (instead of the IDP IFrame server side endpoint).  </p>
<h1 id="rfc.section.3.1.1"><a href="#rfc.section.3.1.1">3.1.1.</a> <a href="#permission_request" id="permission_request">Permission Request</a></h1>
<p id="rfc.section.3.1.1.p.1">The client constructs the request URI by adding the following parameters to the query component of the authorization endpoint URI.  </p>
<p/>

<dl>
  <dt>response_type</dt>
  <dd style="margin-left: 8"><br/> REQUIRED. Value must have "permission".  </dd>
  <dt>client_id</dt>
  <dd style="margin-left: 8"><br/> REQUIRED. The client identifier as described in Section 2.2 of RFC 6749.  </dd>
  <dt>redirect_uri</dt>
  <dd style="margin-left: 8"><br/> OPTIONAL. As described in Section 3.1.2 of RFC 6749.  Or a storagerelay URI as described in Section 3.2 below.  </dd>
  <dt>scope</dt>
  <dd style="margin-left: 8"><br/> OPTIONAL. The scope of the access request as described by Section 3.3 of RFC 6749.  </dd>
  <dt>state</dt>
  <dd style="margin-left: 8"><br/> OPTIONAL. An opaque value used by the client to maintain state between the request and callback.  The authorization server includes this value when directing the user-agent back to the client.  </dd>
</dl>

<p> </p>
<h1 id="rfc.section.3.1.2"><a href="#rfc.section.3.1.2">3.1.2.</a> <a href="#permission_response" id="permission_response">Permission Response</a></h1>
<p id="rfc.section.3.1.2.p.1">After an authorization decision is made on the authorization endpoint, an authorization response is created and sent back to the client that initiates the request.  </p>
<p id="rfc.section.3.1.2.p.2">If the redirect_uri is a storagerelay URI, the client will receive an AuthResult event as defined in section 2.4.3, which holds the authorization response in the authResult field.  </p>
<p id="rfc.section.3.1.2.p.3">If the redirect_uri is not a storagerelay URI, the authorization response will be encoded into the fragment component of the redirection URI.  </p>
<p id="rfc.section.3.1.2.p.4">If end user approve the request, following parameters will be included in the response.  </p>
<p/>

<dl>
  <dt>login_hint</dt>
  <dd style="margin-left: 8"><br/> REQUIRED. The hint of the session that approved the request.  </dd>
  <dt>client_id</dt>
  <dd style="margin-left: 8"><br/> REQUIRED. The client identifier returned to support multiple clients in single relying parties page.  </dd>
  <dt>state</dt>
  <dd style="margin-left: 8"><br/> REQUIRED if the "state" parameter was present in the client authorization request.  The exact value received from the client.  </dd>
</dl>

<p> </p>
<p id="rfc.section.3.1.2.p.6">If end user deny the request, or if there is some error which causes the failure to approve the request, an error response will be generated.  See section 4.2.2.1 of RFC 6749 for the format of an error response.  </p>
<h1 id="rfc.section.3.2"><a href="#rfc.section.3.2">3.2.</a> <a href="#storagerelay_scheme" id="storagerelay_scheme">storagerelay Scheme URI</a></h1>
<p id="rfc.section.3.2.p.1">IDP MUST support storagerelay scheme URI to allow authorization response to be transferred via HTML5 Web Storage in popup mode.  </p>
<p id="rfc.section.3.2.p.2">Below is the format of the storagerelay URI.  </p>
<pre>
  storagerelay://scheme/host?id={requestId}
</pre>
<p/>
<p/>

<dl>
  <dt>scheme</dt>
  <dd style="margin-left: 8"><br/> The scheme of the RP origin. For example, http, https, or chrome-extension.  </dd>
  <dt>host</dt>
  <dd style="margin-left: 8"><br/> The host part of the RP origin. for example, example.com, example.com:8888.  </dd>
  <dt>id</dt>
  <dd style="margin-left: 8"><br/> An id for the request to differentiate the requests for different tabs for the same client.  </dd>
</dl>

<p> </p>
<p id="rfc.section.3.2.p.5">Below is an example storagerelay URI.  </p>
<pre>
  storagerelay://https/rp.com?id=auth304970
</pre>
<p/>
<h1 id="rfc.section.4"><a href="#rfc.section.4">4.</a> <a href="#privacy_considerations" id="privacy_considerations">Privacy Considerations</a></h1>
<p id="rfc.section.4.p.1">Essentially, login hint has similar meaning as the ID token subject, which is defined in OpenID connect specification.  No additional privacy issue should be incurred by the use of login hint in this specification.  </p>
<p id="rfc.section.4.p.2">To protect the End-User from a possible correlation among clients, domain specific login hint SHOULD be used.  </p>
<h1 id="rfc.section.5"><a href="#rfc.section.5">5.</a> <a href="#security_considerations" id="security_considerations">Security Considerations</a></h1>
<p id="rfc.section.5.p.1">Below are some general rules for postMessage, which MUST be followed by both IDP and RP implementers.  </p>
<p/>

<dl>
  <dt>1)</dt>
  <dd style="margin-left: 8">Always verify the sender's identity using the origin and possibly source properties.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">Any window (including, for example, http://evil.example.com) can send a message to any other window, and you have no guarantees that an unknown sender will not send malicious messages.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">For IDP IFrame, the source property MUST be the iframe's direct parent. The origin property MUST be literally same as the value of origin initialization parameter as defined in section 2.1.1.  </dd>
  <dt>2)</dt>
  <dd style="margin-left: 8">Always verify the syntax of the received message.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">Otherwise, a security hole in the site you trusted to send only trusted messages could then open a cross-site scripting hole in your site.  </dd>
  <dt>3)</dt>
  <dd style="margin-left: 8">Always specify an exact target origin, not *, when you use postMessage to send data to other windows.  </dd>
  <dt></dt>
  <dd style="margin-left: 8">A malicious site can change the location of the window without your knowledge, and therefore it can intercept the data sent using postMessage.  </dd>
</dl>

<p> </p>
<h1 id="rfc.references"><a href="#rfc.references">6.</a> Normative References</h1>
<table>
  <tbody>
    <tr>
      <td class="reference">
        <b id="RFC6749">[RFC6749]</b>
      </td>
      <td class="top"><a>Hardt, D.</a>, "<a href="http://tools.ietf.org/html/rfc6749">The OAuth 2.0 Authorization Framework</a>", RFC 6749, DOI 10.17487/RFC6749, October 2012.</td>
    </tr>
    <tr>
      <td class="reference">
        <b id="RFC6819">[RFC6819]</b>
      </td>
      <td class="top"><a>Lodderstedt, T.</a>, <a>McGloin, M.</a> and <a>P. Hunt</a>, "<a href="http://tools.ietf.org/html/rfc6819">OAuth 2.0 Threat Model and Security Considerations</a>", RFC 6819, DOI 10.17487/RFC6819, January 2013.</td>
    </tr>
    <tr>
      <td class="reference">
        <b id="RFC2119">[RFC2119]</b>
      </td>
      <td class="top"><a>Bradner, S.</a>, "<a href="http://tools.ietf.org/html/rfc2119">Key words for use in RFCs to Indicate Requirement Levels</a>", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997.</td>
    </tr>
  </tbody>
</table>
<h1 id="rfc.appendix.A"><a href="#rfc.appendix.A">Appendix A.</a> <a href="#Acknowledgements" id="Acknowledgements">Acknowledgements</a></h1>
<p id="rfc.section.A.p.1">The following individuals contributed ideas, feedback, and wording that shaped and formed the final specification: </p>
<p id="rfc.section.A.p.2">Breno de Medeiros, John Hjelmstad, and Ben Wiley Sittler.  </p>
<h1 id="rfc.authors">
  <a href="#rfc.authors">Authors' Addresses</a>
</h1>
<div class="avoidbreak">
  <address class="vcard">
        <span class="vcardline">
          <span class="fn">Guibin Kong</span> 
          <span class="n hidden">
                <span class="family-name">Kong</span>
          </span>
        </span>
        <span class="org vcardline">Google</span>
        <span class="adr">
          <span class="vcardline">1600 Amphitheatre Pkwy</span>

          <span class="vcardline">
                <span class="locality">Mountain View</span>,  
                <span class="region">CA</span> 
                <span class="code">94043</span>
          </span>
          <span class="country-name vcardline">USA</span>
        </span>
        <span class="vcardline">Phone: +1 650-253-0000</span>

<span class="vcardline">EMail: <a href="mailto:guibinkong@google.com">guibinkong@google.com</a></span>

<span class="vcardline">URI: <a href="http://google.com/">http://google.com/</a></span>

  </address>
</div><div class="avoidbreak">
  <address class="vcard">
        <span class="vcardline">
          <span class="fn">Naveen Agarwal</span> 
          <span class="n hidden">
                <span class="family-name">Agarwal</span>
          </span>
        </span>
        <span class="org vcardline">Google</span>
        <span class="adr">
          <span class="vcardline">1600 Amphitheatre Pkwy</span>

          <span class="vcardline">
                <span class="locality">Mountain View</span>,  
                <span class="region">CA</span> 
                <span class="code">94043</span>
          </span>
          <span class="country-name vcardline">USA</span>
        </span>
        <span class="vcardline">Phone: +1 650-253-0000</span>

<span class="vcardline">EMail: <a href="mailto:naa@google.com">naa@google.com</a></span>

<span class="vcardline">URI: <a href="http://google.com/">http://google.com/</a></span>

  </address>
</div><div class="avoidbreak">
  <address class="vcard">
        <span class="vcardline">
          <span class="fn">William Denniss</span> 
          <span class="n hidden">
                <span class="family-name">Denniss</span>
          </span>
        </span>
        <span class="org vcardline">Google</span>
        <span class="adr">
          <span class="vcardline">1600 Amphitheatre Pkwy</span>

          <span class="vcardline">
                <span class="locality">Mountain View</span>,  
                <span class="region">CA</span> 
                <span class="code">94043</span>
          </span>
          <span class="country-name vcardline">USA</span>
        </span>
        <span class="vcardline">Phone: +1 650-253-0000</span>

<span class="vcardline">EMail: <a href="mailto:wdenniss@google.com">wdenniss@google.com</a></span>

<span class="vcardline">URI: <a href="http://google.com/">http://google.com/</a></span>

  </address>
</div>

</body>
</html>