<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
  <!-- generated by https://github.com/cabo/kramdown-rfc2629 version 1.2.9 -->

<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
<!ENTITY RFC2119 SYSTEM "https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml">
<!ENTITY RFC6749 SYSTEM "https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.6749.xml">
<!ENTITY RFC6750 SYSTEM "https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.6750.xml">
<!ENTITY RFC6755 SYSTEM "https://xml2rfc.tools.ietf.org/public/rfc/bibxml/reference.RFC.6755.xml">
]>


<rfc ipr="trust200902" docName="draft-ietf-oauth-reciprocal-04" category="std">

  <front>
    <title>Reciprocal OAuth</title>

    <author initials="D." surname="Hardt" fullname="Dick Hardt">
      <organization></organization>
      <address>
        <email>dick.hardt@gmail.com</email>
      </address>
    </author>

    <date year="2019" month="August" day="01"/>

    <area>Security</area>
    <workgroup>OAuth Working Group</workgroup>
    

    <abstract>


<t>There are times when a user has a pair of protected resources that would like to request access to each other. While OAuth flows typically enable the user to grant a client access to a protected resource, granting the inverse access requires an additional flow. Reciprocal OAuth enables a more seamless experience for the user to grant access to a pair of protected resources.</t>



    </abstract>


  </front>

  <middle>


<section anchor="introduction" title="Introduction">

<t>In the usual three legged, authorization code grant, the OAuth flow enables a resource owner (user) to enable a client (party A) to be granted authorization to access a protected resource (party B). If party A also has a protected resource that the user would like to let party B access, then a second complete OAuth flow, but in the reverse direction, must be performed. In practice, this is a complicated user experience as the user is at Party A, but the OAuth flow needs to start from Party B. This requires the second flow to send the user back to party B, which then sends the user to Party A as the first step in the flow. At the end, the user is at Party B, even though the original flow started at Party A.</t>

<t>Reciprocal OAuth simplifies the user experience by eliminating the redirections in the second OAuth flow. After the intial OAuth flow, party A obtains consent from the user to grant party B access to a protected resource at party A, and then passes an authorization code to party B using the access token party A obtained from party B to provide party B the context of the user. Party B then exchanges the authorization code for an access token per the usual OAuth flow.</t>

<t>For example, a user would like their voice assistant (party A) and music service (party B) to work together. The voice assistant wants to call the music service to play music, and the music service wants to call the voice assistant with music information to present to the user. The user starts the OAuth flow at the voice assistant, and is redirected to the music service. The music services obtains consent from the user and the redirects back to the voice assistant. At this point the voice assistant is able to obtain an access token for the music service. The voice assistant can the get consent from the user to authorize the music service to access the voice assistant, and then the voice assistant can create an authorization code and send it to the music service, which then exchanges the authorization code for an access token, all without further user interaction. Note that either the voice assistant or the music service can initiate the flow, so that either can prompt the user for the two parties to work together.</t>

<section anchor="terminology" title="Terminology">

<t>In this document, the key words “MUST”, “MUST NOT”, “REQUIRED”,
“SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”,
and “OPTIONAL” are to be interpreted as described in BCP 14, RFC 2119
<xref target="RFC2119"/>.</t>

</section>
</section>
<section anchor="reciprocal-protocol-flow" title="reciprocal Protocol Flow">

<figure><artwork><![CDATA[
 Party A                                         Party B
 +---------------+                               +---------------+
 |               |--(A)- Authorization Request ->|   Resource    |
 |               |                               |   Owner B     |
 |               |<-(B)-- Authorization Grant ---|               |
 |               |                               +---------------+
 |   Client A    |
 |               |                               +---------------+
 |               |--(C)-- Authorization Grant -->|               |
 |               |                               | Authorization |
 |               |<-(D)---- Access Token B ------|   Server B    |
 |               |       reciprocal Request      |               |
 +---------------+                               +---------------+
        |
reciprocal Request
        V
 +---------------+                               +---------------+
 |   Resource    |                               | Authorization |
 |   Owner A     |--(E)--- reciprocal Grant ---->|   Server B    |
 |               |          Access Token B       |               |
 +---------------+                               +---------------+
                                                         |
                                                 reciprocal Grant
                                                         V
 +---------------+                               +---------------+
 |               |<-(F)--- reciprocal Grant -----|               |
 | Authorization |                               |   Client B    |
 |  Server A     |--(G)---- Access Token A ----->|               |
 +---------------+                               +---------------+

 Figure 1: Abstract reciprocal Protocol Flow
]]></artwork></figure>

<t>The reciprocal authorization between party A and party B are abstractly represented in Figure 1 and includes the following steps:</t>

<t><list style="symbols">
  <t>(A - C) are the same as in <xref target="RFC6749"></xref> 1.2</t>
  <t>(D)     Party B optionally includes the reciprocal scope in the response.
        See <xref target="request"/> for details.</t>
  <t>(E)     Party A sends the reciprocal authorization grant to party B.
        See <xref target="code"/> for details.</t>
  <t>(F)     Party B requests an access token, mirroring step (B)</t>
  <t>(G)     Party A issues an access token, mirroring step (C)</t>
</list></t>

<t>Note that Resource Owner A and Resource Owner B are the respective resource owner interaction systems controlled by the same owner.</t>

<section anchor="request" title="Reciprocal Scope Request">

<t>When party B is providing an access token response per <xref target="RFC6749"></xref> 4.1.4, 4.2.1, 4.3.3 or 4.4.3, party B MAY include an additional query component in the redirection URI to indicate the scope requested in the reciprocal grant:</t>

<figure><artwork><![CDATA[
reciprocal OPTIONAL
    The scope of party B's reciprocal access request per [RFC6749] 3.3.
]]></artwork></figure>

<t>If party B does not provide a reciprocal parameter in the access token response, the reciprocal scope will be a value previously preconfigured by party A and party B.</t>

<t>If an authorization code grant access token response per <xref target="RFC6749"></xref> 4.1.4, an example successful response (with extra line breaks for display purposes only):</t>

<figure><artwork><![CDATA[
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "access_token":"2YotnFZFEjr1zCsicMWpAA",
  "token_type":"example",
  "expires_in":3600,
  "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
  "reciprocal":"example_scope",
  "example_parameter":"example_value"
}
]]></artwork></figure>

<t>If an authorization code grant access token response per <xref target="RFC6749"></xref> 4.2.2, an example successful response (with extra line breaks for display purposes only):</t>

<figure><artwork><![CDATA[
HTTP/1.1 302 Found
Location: http://example.com/cb#
    access_token=2YotnFZFEjr1zCsicMWpAA&
    state=xyz&
    token_type=example&
    expires_in=3600&
    reciprocal="example_scope"
]]></artwork></figure>

<t>When party B is providing an authorization response per <xref target="RFC6749"/> 4.1.2, party B MAY include an additional query component in the redirection URI to indicate the scope requested in the reciprocal grant.</t>

<t>reciprocal
      OPTIONAL. The scope of party B’s reciprocal access request per <xref target="RFC6749"/> 3.3.</t>

<t>If party B does not provide a reciprocal parameter in the authorization response, the reciprocal scope will be a value previously preconfigured by party A and party B.</t>

</section>
<section anchor="reciprocal-authorization-flow" title="Reciprocal Authorization Flow">

<t>The reciprocal authorization flow starts after the client (party A) has obtained an access token from the authorization server (party B) per <xref target="RFC6749"/> 4.1 Authorization Code Grant.</t>

<section anchor="user-consent" title="User Consent">
<t>Party A obtains consent from the user to grant Party B access to protected resources at party A. The consent represents the scopes requested by party B from party A per <xref target="request"/>.</t>

</section>
<section anchor="code" title="Reciprocal Authorization Code">
<t>Party A generates an authorization code representing the access granted to party B by the user. Party A then makes a request to party B’s token endpoint authenticating per <xref target="RFC6749"/> 2.3 and sending the following parameters using the “application/x-www-form-urlencoded” format per <xref target="RFC6749"/> Appendix B with a character encoding of UTF-8 in the HTTP request entity-body:</t>

<figure><artwork><![CDATA[
grant_type REQUIRED
    Value MUST be set to "urn:ietf:params:oauth:grant-type:reciprocal".

code REQUIRED
    the authorization code generated by party A.

client_id REQUIRED
    party A'a client ID.
]]></artwork></figure>

<t>access_token REQUIRED
        the access token obtained from Party B. Used by Party B to identify which user authorization is being requested.</t>

<t>For example, the client makes the following HTTP request using TLS (with extra line breaks for display purposes only):</t>

<figure><artwork><![CDATA[
 POST /token HTTP/1.1
 Host: server.example.com
 Authorization: Basic ej4hsyfishwssjdusisdhkjsdksusdhjkjsdjk
 Content-Type: application/x-www-form-urlencoded

 grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3reciprocal
   &code=hasdyubasdjahsbdkjbasd
   &client_id=example.com
   &access_token=sadadojsadlkjasdkljxxlkjdas
]]></artwork></figure>

<t>Party B MUST verify the authentication provided by Party A per <xref target="RFC6749"/> 2.3</t>

<t>Party B MUST then verify the access token was granted to the client identified by the client_id.</t>

<t>Party B MUST respond with either an HTTP 200 (OK) response if the request is valid, or an HTTP 400 “Bad Request” if it is not.</t>

<t>Party B then plays the role of the client to make an access token request per <xref target="RFC6749"/> 4.1.3.</t>

</section>
</section>
</section>
<section anchor="authorization-update-flow" title="Authorization Update Flow">

<t>After the initial authorization, the user may add or remove scopes available to the client at the authorization server. For example, the user may grant additional scopes to the client using a voice interface, or revoke some scopes. The authorization server can update the client with the new authorization by sending a new authorization code per <xref target="code"/>.</t>

</section>
<section anchor="iana-considerations" title="IANA Considerations">

<section anchor="registration-of-reciprocal" title="Registration of reciprocal">

<t>This section registers the value “reciprocal” in the IANA “OAuth Parameters” registry established by “The OAuth 2.0 Authorization Framework” <xref target="RFC6749"></xref>.</t>

<t><list style="symbols">
  <t>Parameter Name: reciprocal</t>
  <t>Parameter usage location: token response</t>
  <t>Change Controller: IESG</t>
  <t>Specification Document: Section <xref target="request"/> of this document</t>
</list></t>

</section>
<section anchor="sub-namespace-registration-of-urnietfparamsoauthgrant-typereciprocal" title="Sub-Namespace Registration of urn:ietf:params:oauth:grant-type:reciprocal">

<t>This section registers the value “grant-type:reciprocal” in the IANA
“OAuth URI” registry established by “An IETF URN Sub-Namespace for OAuth” <xref target="RFC6755"></xref>.</t>

<t><list style="symbols">
  <t>URN: urn:ietf:params:oauth:grant-type:reciprocal</t>
  <t>Common Name: reciprocal grant for OAuth 2.0</t>
  <t>Change Controller: IESG</t>
  <t>Specification Document: Section <xref target="code"/> of this document</t>
</list></t>

</section>
</section>


  </middle>

  <back>

    <references title='Normative References'>

&RFC2119;
&RFC6749;
&RFC6750;
&RFC6755;


    </references>



<section anchor="document-history" title="Document History">

<section anchor="draft-ietf-oauth-reciprocal-00" title="draft-ietf-oauth-reciprocal-00">

<t><list style="symbols">
  <t>Initial version.</t>
</list></t>

</section>
<section anchor="draft-ietf-oauth-reciprocal-01" title="draft-ietf-oauth-reciprocal-01">

<t><list style="symbols">
  <t>Changed reciprocal scope request to be in access token response rather than authorization request</t>
</list></t>

</section>
<section anchor="draft-ietf-oauth-reciprocal-02" title="draft-ietf-oauth-reciprocal-02">

<t><list style="symbols">
  <t>Added in diagram to clarify protocol flow</t>
</list></t>

</section>
<section anchor="draft-ietf-oauth-reciprocal-03" title="draft-ietf-oauth-reciprocal-03">

<t><list style="symbols">
  <t>fixed spelling of reciprocal</t>
  <t>added example use case in introduction</t>
  <t>resource owner is the same in Party A and Party B</t>
</list></t>

</section>
<section anchor="draft-ietf-oauth-reciprocal-04" title="draft-ietf-oauth-reciprocal-04">

<t><list style="symbols">
  <t>completed IANA section</t>
</list></t>

</section>
</section>


  </back>

<!-- ##markdown-source:
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
AAA=

-->

</rfc>

