<?xml version="1.0" encoding="utf-8"?>
<?xml-model href="rfc7991bis.rnc"?>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>

<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>

<rfc
  xmlns:xi="http://www.w3.org/2001/XInclude"
  category="info"
  docName="draft-vandermeulen-oauth-resource-helper-00"
  ipr="trust200902"
  obsoletes=""
  updates=""
  submissionType="IETF"
  xml:lang="en"
  version="3">

  <front>
    <title abbrev="OAuth Resource Helper">OAuth Resource Helper</title>

    <seriesInfo name="Internet-Draft" value="draft-vandermeulen-oauth-resource-helper-00"/>

    <author fullname="Pieter van der Meulen" initials="P.G.M." surname="van der Meulen">
      <organization>SURF</organization>
      <address>
        <postal>
          <street>Moreelsepark 48</street>
          <code>3511 EP</code>
          <city>Utrecht</city>
          <country>NL</country>
        </postal>
        <email>pieter.vandermeulen@surf.nl</email>
      </address>
    </author>

    <author fullname="Michiel de Jong" initials="M.B." surname="de Jong">
      <organization>Ponder Source</organization>
      <address>
        <postal>
          <street>Torenlaan 5A</street>
          <code>1402 AT</code>
          <city>Bussum</city>
          <country>NL</country>
        </postal>
        <email>michiel@unhosted.org</email>
      </address>
    </author>

    <date year="2024"/>

    <area>General</area>
    <workgroup>Internet Engineering Task Force</workgroup>

    <keyword>OAuth</keyword>
    <keyword>Resource Helper</keyword>

    <abstract>
      <t>
        This Internet Draft introduces the concept of a Resource Helper in OAuth 2.0.
        A Resource Helper is a modular component that assists the Authorization Server in managing fine-grained authorization processes.
        The Resource Helper, associated with a specific Resource Server, handles scope selection and resource-specific details,
        providing the user-interface for the Resource Owner to approve or refine access requests.
        By offloading scope-related user interaction to the Resource Helper,
        the Authorization Server remains generic and stable while the Resource Helper evolves alongside the Resource Server's requirements.
        This specification defines the protocol, interfaces, and flow between the Authorization Server and the Resource Helper.
        Introducing a Resource Helper does not affect the OAuth client or the interaction between the OAuth client and the Resource Server.
      </t>
    </abstract>

  </front>

  <middle>

    <section>
      <name>Introduction</name>
      <t>
        In OAuth 2.0 <xref target="RFC6749" /> an authorization server is responsible for the authorization process.
        We introduce a resource helper, which is a separate component that can handle part of the OAuth Grant Flow of the authorization server,
        making the authorization server more modular.
        A Resouce Helper is associated with a specific resource server and provides the user interface for the resource owner to pick Access Token Scopes
        <xref target="RFC6749" section="3.3" sectionFormat="parens" />,
        and possibly other resource server specific information to put in the Access Token, or in an Introspection Response <xref target="RFC7662" section="2.2" sectionFormat="parens" />.
        This allows an authorization server to remain generic and stable, while the resource helper can be updated in lock-step with the functionality of the resource server.
        This document describes the protocol and interface between the authorization server and the resource helper.
      </t>
      <t>
        During an OAuth 2.0 Authorization Grant Flow,
        the authorization server authenticates the resource owner (via the user agent)
        and establishes whether the resource owner (partially) grants or denies the client's request for a token.
        For the authorization server to meaningfully measure if the resource owner wants to grant or deny the request
        it needs to display, presumably via the user agent,
        the details of the authorization that the resource owner is about to give in a way that they will understand.
        These details can be very specific for the resource server's current functionality,
        especially when the resource owner wants to provide a more fine-grained authorization than just "yes" or "no".
        For example when the resource owner only wants to allow specific kinds of operations on specific resources, like
        "allow the client to view these three pictures, but not to delete them", or "allow the client write access to only this specific directory".
      </t>
      <t>
        Several extension to OAuth 2.0 have been created to allow for more control over the authorization process outside of the authorization server.
      </t>
      <ul>
        <li>
          In OAuth 2.0 Rich Authorization Requests<xref target="RFC9396" />, the client includes a JSON description with the
          <tt>authorization_details</tt> of the requested authorization in the Authorization Request to the authorization server.
          This requires the client and the resource server to agree on the format and meaning of the authorization_details so that the client can create it
          and the authorization server can interpret it and display it to the resource owner.
        </li>
        <li>
          In Resource Set Registration as proposed in <xref target="UMA-Fed-Authz" /> and similarly in <xref target="I-D.ietf-gnap-resource-servers"/>,
          an API is defined on the authorization server to allow a resource server to register
          Resource Sets at the authorization server. A resource set consists of scopes, a description and an icon to allow the authorization server to display
          the available resource sets to the resource owner in a meaningful way.
        </li>
      </ul>
      <t>
        The role of the resource helper we propose is smaller and more interactive than these existing OAuth extensions.
        Displaying access token scope details via the user agent may involve describing specific resources and actions,
        in a human-viewable, probably locale-dependent, and possibly even persona-dependent way,
        using a combination of text, images, and layout.
        The resource helper executes this task entirely, leaving the authorization server more generic and stable.
      </t>

      <section>
        <name>Requirements Language</name>
        <t>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 BCP 14
          <xref target="RFC2119"/>
          <xref target="RFC8174"/>
          when, and only when, they appear in
          all capitals, as shown here.
        </t>
      </section>
    </section>

    <section>
      <name>Generic Flow</name>
      <t>
        The figure below shows the interaction between the authorization server and the resource helper
        when a client starts the authorization grant process.
      </t>
      <figure anchor="seq">
        <artwork alt="Interaction between client, authorization server and resource helper" type="ascii-art" src="https://raw.githubusercontent.com/SURFnet/surf-token-based-access/refs/heads/main/phase-3/spec/seq.txt"/>
      </figure>
      <ul>
        <li>
          (A): The OAuth client initiates the authorization grant process by sending a request to the authorization server.
        </li>
        <li>
          (B): The authorization server authenticates the user and then redirects the user (via their user agent) to the "Pick" endpoint of the Resource Helper that is registered for the resource server.
          This redirection includes a unique nonce and, optionally, the scope parameter specified by the client, to initiate the scope selection process.
        </li>
        <li>
          (C): The Resource Helper may call the authorization server's "Subject Info" to retrieve additional user-specific information (e.g., a username or other identifiers).
          This call uses the nonce from step B and the resource helper's credentials to authenticate this request.
        </li>
        <li>
          (D): Once the user has selected their desired scope and permissions,
          the Resource Helper submits this choice to the authorization server.
          This submission includes the scope, optional token payload, optional introspection details,
          and a label with a description of the access that was granted.
          This call uses the nonce from step B and the resource helper's credentials to authenticate this request.
        </li>
        <li>
          (E): The authorization server processes the Resource Helper's submission.
          It finalizes the scope and token details and prepares the access token for the client.
        </li>
        <li>
          (F): The authorization server issues the access token to the client, completing the flow.
        </li>
      </ul>
    </section>

    <section>
      <name>Resource Helper Registry</name>
      <t>
        The authorization server SHOULD maintain a registry of trustworthy resource helpers,
        containing for each resource helper:
      </t>
      <ul>
        <li>a fully qualified domain name (for `/.well-known/resource-helper` lookup, see below)</li>
        <li>client credentials</li>
        <li>which scope-picking tasks it can be used for</li>
      </ul>
      <t>
        The authorization server SHOULD NOT redirect the end user to resource helpers other than the ones
        from this registry.
        It SHOULD also NOT accept choice submissions from resource helpers other than the ones
        from this registry.
      </t>
    </section>

    <section>
      <name>Resource Helper Well-Known Endpoint</name>
      <t>
        At its `/.well-known/resource-helper` end point, the resource helper SHOULD serve a JSON document,
        containing an object with a member whose key is &quot;pick&quot; and whose value is the front channel
        URL for the pick endpoint to which the authorization server can redirect the user.
     </t>
    </section>

    <section>
      <name>Resource Helper Configuration</name>
      <t>
        The resource helper needs to persist:
      </t>
      <ul>
        <li>the `choice` back channel endpoint URL of the authorization server</li>
        <li>(optional) the <tt>subject_info</tt> back channel endpoint URL of the authorization server</li>
        <li>the front channel callback URL of the authorization server</li>
        <li>its client credentials for use in backchannel calls to the authorization server</li>
      </ul>
    </section>

    <section>
      <name>Resource Helper Pick Endpoint</name>
      <t>
        The authorization server can redirect the end user to the resource helper's Pick endpoint, with the
        following query parameters:
     </t>
      <ul>
        <li>a nonce for this interaction</li>
        <li>(optional) the scope parameter as specified by the client (if any)</li>
      </ul>
      <t>
        Example: <tt>https://resource-helper.example.com/pick?nonce=12345678&amp;scope=read</tt>
      </t>
    </section>

    <section>
      <name>Subject Info Lookup</name>
      <t>
        The resource helper can optionally make a HTTP call to the Subject Info endpoint of the authorization server,
        with the nonce from the pick request in the query parameter to obtain more information about the end user.
        Apart from checking the value of the nonce query parameter, the authorization server SHOULD check the Authorization
        header to establish authentication of the resource helper before responding with any restricted information.
        Example request:
      </t>
      <sourcecode><![CDATA[
GET /subject-info?nonce=12345678 HTTP/1.1
Host: authorization-server.example.com
Authorization: &lt;...&gt;
      ]]>
      </sourcecode>
      <t>
        Example response:
      </t>
      <sourcecode><![CDATA[
{
  "username": "polly123@example.com"
}
        ]]>
      </sourcecode>
      <t>
        Alternatively, the resource helper could skip this step and instead take its own end user authentication measures.
      </t>
    </section>

    <section>
      <name>Picking Access Token Scopes</name>
      <t>
        The resource helper will guide the end user in picking access scopes.
        Note that it is the responsibility of the resource helper to help the end user make the right decisions
        here. The choice will be opaque to the authorization server, to eventually be interpreted by the Resource
        Server during resource access.
      </t>
    </section>

    <section>
      <name>Human-readable Label</name>
      <t>
        Even though the detailed view of an access scope can only be provided by the resource helper,
        it is still useful if the authorization server can at least display a string label.
        In particular, when the authorization server displays the final confirmation dialog,
        to grant the selected scope to the client in question,
        it could display this label in much the same way as it will likely display some label for the client's identity there.
        Also, when displaying a list of currently valid tokens, with the option to revoke,
        displaying a list of one-line labels could be convenient there.
      </t>
      <t>
        This label could be produced programmatically by the resource helper, or hand-picked by the resource owner.
      </t>
    </section>

    <section>
      <name>Introspect and Token Payload Options</name>
      <t>
        To make it easier for existing resource servers to start accepting access tokens issued by the authorization server,
        some custom arrangements may be included in the resource helper's software, that interact well with the resource server's
        existing processes and policies.
        To facilitate this, the authorization server MUST allow the resource helper to specify opaque data to be included in the access token payload
        and in the token introspect response.
      </t>
      <t>
        The resource helper might also share state with the resource server
        that helps the resource server to understand the scope of the access tokens issued by the authorization server,
        for instance through a database backend that is shared between the resource helper and the resource server.
      </t>
    </section>

    <section>
      <name>The Choice Endpoint</name>
      <t>
        After allowing the user to pick an access scope, the resulting choice submission would include:
      </t>
      <ul>
        <li>nonce (the nonce from the previous steps)</li>
        <li>action (must contain the string "grant" or the string "deny" as appropriate)</li>
        <li>label (a human-readable string for display in for instance the authorization server's token revokation interface)</li>
        <li>(optional) a scope field, if different from the one that was requested (to be passed back to the client)</li>
        <li>(optional) an opaque payload object (to be included in the access token payload)</li>
        <li>(optional) an opaque introspect object (to be included in the introspection response for the access token, if applicable)</li>
      </ul>
      <t>
        Apart from the inclusion of the nonce which binds this back channel call to the initial front channel redirect
        (step B in <xref target="seq"/>),
        the resource helper MUST also provide credentials that can identify it as a trusted member of the authorization server's
        resource helper Registry, for instance through an `Authorization` header as agreed between authorization server and resource helper,
        and this request MUST be made over TLS, to the choice endpoint of the authorization server.
      </t>
      <t>
        Here is a non-normative example:
      </t>
      <sourcecode><![CDATA[
POST /choice
Content-Type: application/json
Authorization: &lt;...&gt;

{
  "nonce": "12345678",
  "action": "grant",
  "label": {
    "en-US": "John's picture number 4 (write access)"
  },
  "scope": "/home/john/pictures/4:write",
  "payload": {
    "user": "john"
  },
  "introspect": {
    "path": "storage-5:~pictures/4",
    "modes": "rwx"
  },
}
      ]]>
      </sourcecode>
    </section>

    <section>
      <name>Redirect Back to the Authorization Server</name>
      <t>
        After the choice information has been successfully submitted to the authorization server, the end user can be
        redirected back to the authorization server to continue the OAuth flow as usual. This redirect MUST contain
        the nonce for this interaction in the query parameter, and <tt>result=ok</tt> if all steps were completed
        successfully. Other values for the <tt>result</tt> query parameter SHOULD be used to indicate different types
        of errors:
      </t>
      <ul>
        <li>ok: all steps completed successfully</li>
        <li>deny: if <tt>action: deny</tt> was passed in the choice call</li>
        <li>unauth: if no end user could be authenticated</li>
        <li>cancel: if the end user chose to abort the process</li>
        <li>error: if the back channel call to the choice end point resulted in no response or in an error response</li>
        <li>invalid: if the resource helper could not unambiguously interpret its task</li>
        <li>fail: if the resource helper was unable to perform it tasks for other reasons</li>
      </ul>
      <t>
        Example: <tt>https://authorization-server.example.com/callback?nonce=12345678&amp;result=ok</tt>.
      </t>
    </section>

    <section anchor="IANA">
      <name>IANA Considerations</name>
      <t>This memo includes no request to IANA.</t>
    </section>

    <section anchor="Security">
      <name>Security Considerations</name>
      <t>
        It is important to understand the value of the choice submission from resource helper to authorization server.
        It already contains an access grant as a half-product,
        for the authorization server to finalize by actually issuing it to a client.
      </t>
      <t>
        This model differs from the Lodging Intent pattern used in<xref target="FAPI-CIBA"/>,
        where the intent is only a description of some intended transaction,
        directly between client and resource server,
        and from Resource Registries
        as described in section 3.4 of <xref target="I-D.ietf-gnap-resource-servers"/>,
        or as described in section 3.2 of <xref target="UMA-Fed-Authz"/>,
        which only describe a resource.
      </t>
      <t>
        The choice submission represents more than a description of a transaction scope or a
        resource registration.
        It additionally represents an assessment that this description was intentionally
        composed or approved by an authenticated resource owner, authorized to
        grant access to such resources, actually taking an active decision to grant such
        access.
      </t>
      <t>
        What it does not include is the information to which particular client they will grant it.
        That remains the jurisdiction of the authorization server.
      </t>
      <t>
        The resource helper MUST NOT display any information that the currently authenticated user is not allowed to see,
        even if it is instructed to display them through the scope parameter that comes from the authorization server.
      </t>
      <t>
        The resource helper MUST only allow picking resources for which the currently authenticated user is a resource owner.
        The resulting access token scope MUST always be a subset (attenuation) of the resource owner's own access scope.
      </t>
      <t>
        The scope coming back from the resource helper SHOULD be interpretable outside the context of a specific user.
        For instance, a scope "my-billing-details:read" means different things for different resource owners.
        To avoid confusion, especially if authentication was handled through the authorization server's <tt>user_info</tt> end point (see above),
        use a globally unambiguous scope identifier such as "user-123:billing-detals:read".
      </t>
    </section>
  </middle>

  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        <!-- Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words -->
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
        <!-- Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words -->
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
      </references>

      <references>
        <name>Informative References</name>
        <!-- The OAuth 2.0 Authorization Framework -->
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6749.xml"/>

        <!-- Token introspection -->
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7662.xml"/>

        <!-- OAuth 2.0 Rich Authorization Requests -->
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9396.xml"/>

        <xi:include href="https://datatracker.ietf.org/doc/bibxml3/draft-ietf-gnap-resource-servers-05.xml"/>

        <reference anchor="UMA-Fed-Authz"
                   target="https://docs.kantarainitiative.org/uma/wg/rec-oauth-uma-federated-authz-2.0.html">
          <front>
            <title>UMA Federated Authorization</title>
            <author initials="E." surname="Maler">
              <organization/>
            </author>
            <date year="2018"/>
          </front>
        </reference>

        <reference anchor="FAPI-CIBA"
                   target="https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html">
          <front>
            <title>UMA Federated Authorization</title>
            <author initials="G." surname="Fernandez">
              <organization/>
            </author>
            <date year="2021"/>
          </front>
        </reference>
      </references>
    </references>
  </back>
</rfc>
