<?xml version="1.0" encoding="utf-8"?>
<!-- name="GENERATOR" content="github.com/mmarkdown/mmark Mmark Markdown Processor - mmark.miek.nl" -->
<rfc version="3" ipr="trust200902" docName="draft-wullink-rpp-oauth2-00" submissionType="IETF" category="std" xml:lang="en" xmlns:xi="http://www.w3.org/2001/XInclude" indexInclude="true" tocDepth="4">

<front>
<title abbrev="OAuth 2.0 for RPP">OAuth 2.0 for RESTful Provisioning Protocol (RPP)</title><seriesInfo value="draft-wullink-rpp-oauth2-00" stream="IETF" status="standard" name="Internet-Draft"></seriesInfo>
<author initials="M." surname="Wullink" fullname="Maarten Wullink"><organization>SIDN Labs</organization><address><postal><street></street>
</postal><email>maarten.wullink@sidn.nl</email>
<uri>https://sidn.nl/</uri>
</address></author><author initials="P." surname="Kowalik" fullname="Pawel Kowalik"><organization>DENIC</organization><address><postal><street></street>
</postal><email>pawel.kowalik@denic.de</email>
<uri>https://denic.de/</uri>
</address></author><date year="2026" month="July" day="6"></date>
<area>Internet</area>
<workgroup>Network Working Group</workgroup>

<abstract>
<t>This document describes how OAuth 2.0 <xref target="RFC6749"></xref> can be used to secure RESTful Provisioning Protocol (RPP) API requests described in <xref target="I-D.ietf-rpp-core"></xref>.</t>
</abstract>

</front>

<middle>

<section anchor="introduction"><name>Introduction</name>
<t>In order to allow for fine-grained access control, which is a key design goal of RPP's authorization model, a registrar can operate multiple user accounts within the registry. Each account carries a distinct set of permissions appropriate to the user's or tool's role (e.g., read-only reporting accounts, accounts limited to a specific set of operations, or fully privileged administrative accounts). This allows registrars to implement the principle of least privilege within their own organizations without requiring separate registry-level registrar accounts.</t>
<t>Due to the stateless nature of RPP, the client includes authorization credentials in each HTTP request. RPP uses OAuth 2.0 <xref target="RFC6749"></xref> for delegated authorization via Bearer tokens. Basic authentication <xref target="RFC7617"></xref> SHOULD NOT be used. The server MUST validate the Bearer token on each request and reject any request with an invalid or expired token with an appropriate HTTP status code.</t>
</section>

<section anchor="terminology"><name>Terminology</name>
<t>In this document the following terminology is used.</t>
<t>URL - A Uniform Resource Locator as defined in <xref target="RFC3986"></xref>.</t>
<t>Resource - An object having a type, data, and possible relationship to other resources, identified by a URL.</t>
<t>RPP client - An HTTP user agent performing an RPP request</t>
<t>RPP server - An HTTP server responsible for processing requests and returning results in any supported media type.</t>
<t>JWT - JSON Web Token as defined in <xref target="RFC7519"></xref>.</t>
<t>Authorization Server (AS) - A server that issues OAuth 2.0 access tokens to clients after successfully authenticating the resource owner and obtaining authorization, as defined in <xref target="RFC6749"></xref>.</t>
<t>Resource Server (RS) - A server hosting protected resources that accepts and validates OAuth 2.0 access tokens to authorize requests, as defined in <xref target="RFC6749"></xref>.</t>
<t>Client - An application making protected resource requests on behalf of the resource owner and with its authorization, as defined in <xref target="RFC6749"></xref>.</t>
<t>Resource Owner - An entity capable of granting access to a protected resource. When the resource owner is a person, it is referred to as an end-user, as defined in <xref target="RFC6749"></xref>.</t>
<t>Access Token - A credential used by a client to access protected resources. In RPP, access tokens MUST be JWTs conforming to <xref target="RFC9068"></xref>.</t>
<t>Bearer Token - A type of access token where any party in possession of the token can use it to access the associated resource, as defined in <xref target="RFC6750"></xref>.</t>
<t>Client Credentials Grant - An OAuth 2.0 grant type in which the client authenticates directly with the AS using its own credentials to obtain an access token, without end-user involvement, as defined in <xref target="RFC6749" sectionFormat="bare" section="Section 4.4"></xref>. Used for machine-to-machine flows.</t>
<t>Authorization Code Grant - An OAuth 2.0 grant type in which the client obtains an authorization code from the AS via a user-agent redirect, then exchanges it for an access token, as defined in <xref target="RFC6749" sectionFormat="bare" section="Section 4.1"></xref>. Used for interactive flows involving end-users.</t>
<t>PKCE (Proof Key for Code Exchange) - An extension to the Authorization Code Grant that prevents authorization code interception attacks, as defined in <xref target="RFC7636"></xref>.</t>
<t>Scope - A mechanism in OAuth 2.0 to limit the access granted by an access token, as defined in <xref target="RFC6749"></xref>. RPP uses scopes to enforce fine-grained access control over provisioning operations.</t>
<t>OAuth 2.0 AS Metadata - A mechanism for ASs to publish their configuration and capabilities at a well-known URL, as defined in <xref target="RFC8414"></xref>.</t>
<t>Rich Authorization Requests (RAR) - An OAuth 2.0 extension that allows clients to request fine-grained authorization data beyond what scopes can express, as defined in <xref target="RFC9396"></xref>.</t>
</section>

<section anchor="conventions-used-in-this-document"><name>Conventions Used in This Document</name>
<t>The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;,&quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in <xref target="RFC2119"></xref>.</t>
<t>In examples, indentation and white space are provided only to illustrate element relationships and are not REQUIRED features of the protocol.</t>
<t>All example requests assume an RPP server using HTTP version 2 is listening on the standard HTTPS port on host rpp.example. An authorization token has been provided by an out-of-band process and MUST be used by the client to authenticate each request.</t>
</section>

<section anchor="architectural-overview"><name>Architectural Overview</name>
<t>The diagram below gives an overview of all actors and their relationships in the RPP OAuth 2.0 architecture. The Registry operates both the Authorization Server (AS) and the RPP server. The Registrar operates the Registrar Backend, which is an RPP client, and may also operate its own AS. The Registry Employee and Registrar Employee are human operators that interact with the registry and registrar systems via a web browser. The Registry Client App is a client application operated by the registry on behalf of the Registry Employee, while the Registrar Backend is a client application operated by the registrar on behalf of the Registrar Employee and for automated operations. Both client applications interact with the RPP server using OAuth 2.0 Bearer tokens for authorization.</t>
<figure><name>RPP OAuth 2.0 Architecture Overview
</name>
<sourcecode type="ascii"><![CDATA[  +------------------------------------------------------------------+
  |                           Registry                               |
  |                                                                  |
  |  +--------------------+   +--------------+   +---------------+   |
  |  | Authorization      |   | Registry     |   |  RPP Server   |   |
  |  | Server (AS)        |<--| Client App   |-->| (Res. Server) |   |
  |  |                    |   |              |   +---------------+   |
  |  +--------------------+   +--------------+              ^        |
  |        ^   ^      ^             ^                       |        |
  |        |   |      |             |                       |        |
  |        |   |      |             |                       |        |
  |        |   |      |    +--------------------+           |        |
  |        |   |      +----| Registry Employee  |.          |        |
  |        |   |           | (Browser)          |           |        |
  |        |   |           +--------------------+           |        |
  +--------|---|--------------------------------------------|--------+
           |   |                                            |
           |   |----------------+                           |
           |                    |                           |
   +------------------+   +------------------+              |
   | Registrar        |<--+ Registrar        |              |
   | Backend          |   | Employee         |              |
   | (RPP API Client) |   | (Browser)        |              |
   +------------------+   +------------------+              |
            |                                               |
            +------>  RPP Request to RPP Server-------------+
]]>
</sourcecode>
</figure>
<t>The actors in the diagram are as follows:</t>

<ul spacing="compact">
<li><strong>Registry AS</strong>: The OAuth 2.0 Authorization Server operated by the registry. All access tokens are issued by this AS. It is the single trust anchor for RPP authorization.</li>
<li><strong>Registry RPP Server</strong>: The OAuth 2.0 Resource Server that exposes the RPP API. It validates Bearer tokens issued by the Registry AS before processing any request.</li>
<li><strong>Registry Client App</strong>: A client application operated by the registry. The Registry Employee authenticates with the AS via the Authorization Code grant, receives the token, and uses the Registry Client App. The Registry Client App also exchanges the authorization code for a token directly at the AS, then sends RPP requests to the RPP server on the employee's behalf.</li>
<li><strong>Registry Employee (Browser)</strong>: A human operator at the registry. Authenticates directly with the Registry AS using the Authorization Code grant, receives a token, and uses the Registry Client App to interact with the RPP server.</li>
<li><strong>Registrar Backend (RPP API Client)</strong>: The registrar's backend system that communicates directly with the RPP server. It obtains tokens using either the Client Credentials grant for automated M2M operations, or the Authorization Code grant when acting on behalf of an authenticated registrar employee. It sends all RPP requests to the RPP server.</li>
<li><strong>Registrar Employee (Browser)</strong>: A human operator at the registrar. Authenticates directly with the Registry AS using the Authorization Code grant, after which the token is delivered to the Registrar Backend via redirect callback. The employee uses the Registrar Backend to interact with the RPP server.</li>
</ul>
</section>

<section anchor="authorization"><name>Authorization</name>
<t>RPP MAY use OAuth 2.0 <xref target="RFC6749"></xref> as its authorization framework. OAuth 2.0 is an authorization protocol and does not perform authentication itself; authentication of the client or end-user is handled by the AS before a token is issued. RPP acts as an OAuth 2.0 Resource Server and MUST validate every incoming request against a Bearer token presented in the <tt>Authorization</tt> header. The registry MAY operate its own Authorization Server (AS) or MAY delegate to an external AS. Access control decisions are derived exclusively from claims in the presented JWT access token.</t>
<t>Access tokens MUST be JWTs conforming to the JWT Profile for OAuth 2.0 Access Tokens <xref target="RFC9068"></xref>. Tokens MUST be signed using asymmetric cryptography; symmetric signing algorithms (e.g., HS256) MUST NOT be used for tokens issued by external ASs. Short-lived tokens are RECOMMENDED and token caching and refresh strategies MUST follow the best practices defined in <xref target="RFC8725"></xref>.</t>
<t>An RPP server determines what AS issued a token by inspecting the <tt>iss</tt> claim; the RPP server MUST validate the token's signature against the issuing AS's public key, which may be fetched and cached via OAuth 2.0 AS Metadata <xref target="RFC8414"></xref> or by an out-of-band mechanism.</t>
<t>In both modes authorization is enforced identically. The <tt>aud</tt> claim MUST identify the RPP server as the intended audience; the RPP server MUST reject tokens where its own identifier is absent from <tt>aud</tt>.</t>
<t>RPP MUST support the <tt>Client Credentials Grant</tt> grant type described in <xref target="RFC6749" sectionFormat="bare" section="Section 4.4"></xref> to allow registrar client systems to obtain access tokens.</t>
</section>

<section anchor="scopes"><name>Scopes</name>
<t>OAuth 2.0 scopes are used for granting authorization and enforcing access control when accessing RPP resources. The server MUST define a set of scopes that can be requested by clients when obtaining access tokens. The server MUST also define the mapping between scopes and the specific resources and operations that they grant access to.</t>
<t>RPP scopes are based on the objects, processes and operations defined in <xref target="I-D.ietf-rpp-data-objects"></xref>. Each scope corresponds to a specific set of permissions for accessing and manipulating RPP resources.</t>

<section anchor="scope-derivation-rules"><name>Scope Derivation Rules</name>
<t>RPP scopes are derived systematically from the data object types and operation categories defined in <xref target="I-D.ietf-rpp-data-objects"></xref>. The derivation rules are as follows:</t>

<ul spacing="compact">
<li>The scope identifier MUST use the format <tt>&lt;object&gt;:&lt;access-level&gt;</tt>, where <tt>&lt;object&gt;</tt> is the lowercase stable identifier of the data object and <tt>&lt;access-level&gt;</tt> is one of the access levels defined below based on the object operation.</li>
<li>The <tt>create</tt> access level grants permission to perform the Create operation.</li>
<li>The <tt>read</tt> access level grants permission to perform the Read operation.</li>
<li>The <tt>update</tt> access level grants permission to perform the Update operation.</li>
<li>The <tt>renew</tt> access level grants permission to perform the Renew operation.</li>
<li>The <tt>restore</tt> access level grants permission to perform the Restore operation.</li>
<li>The <tt>delete</tt> access level grants permission to perform the Delete operation.</li>
<li>The <tt>transfer</tt> access level grants permission to perform all Transfer operations.</li>
<li>The <tt>list</tt> access level grants permission to perform List operations.</li>
</ul>
</section>

<section anchor="scope-registry"><name>Scope Registry</name>
<t>Table <xref target="tbl-scopes"></xref> defines the RPP scopes derived from the data objects specified in <xref target="I-D.ietf-rpp-data-objects"></xref>.</t>
<table anchor="tbl-scopes"><name>RPP OAuth 2.0 Scopes</name>
<thead>
<tr>
<th>Scope</th>
<th>Data Object</th>
<th>Operations Granted</th>
</tr>
</thead>

<tbody>
<tr>
<td><tt>domain:create</tt></td>
<td>Domain Name</td>
<td>Create</td>
</tr>

<tr>
<td><tt>domain:read</tt></td>
<td>Domain Name</td>
<td>Read</td>
</tr>

<tr>
<td><tt>domain:update</tt></td>
<td>Domain Name</td>
<td>Update</td>
</tr>

<tr>
<td><tt>domain:renew</tt></td>
<td>Domain Name</td>
<td>Renew</td>
</tr>

<tr>
<td><tt>domain:restore</tt></td>
<td>Domain Name</td>
<td>Restore</td>
</tr>

<tr>
<td><tt>domain:delete</tt></td>
<td>Domain Name</td>
<td>Delete</td>
</tr>

<tr>
<td><tt>domain:transfer</tt></td>
<td>Domain Name</td>
<td>Create, Approve, Reject, Cancel, Query</td>
</tr>

<tr>
<td><tt>domain:list</tt></td>
<td>Domain Name</td>
<td>List domain collection</td>
</tr>

<tr>
<td><tt>contact:create</tt></td>
<td>Contact</td>
<td>Create</td>
</tr>

<tr>
<td><tt>contact:read</tt></td>
<td>Contact</td>
<td>Read</td>
</tr>

<tr>
<td><tt>contact:update</tt></td>
<td>Contact</td>
<td>Update, Restore</td>
</tr>

<tr>
<td><tt>contact:delete</tt></td>
<td>Contact</td>
<td>Delete</td>
</tr>

<tr>
<td><tt>contact:transfer</tt></td>
<td>Contact</td>
<td>Create, Approve, Reject, Cancel, Query</td>
</tr>

<tr>
<td><tt>contact:list</tt></td>
<td>Contact</td>
<td>List contact collection</td>
</tr>

<tr>
<td><tt>host:create</tt></td>
<td>Host</td>
<td>Create</td>
</tr>

<tr>
<td><tt>host:read</tt></td>
<td>Host</td>
<td>Read</td>
</tr>

<tr>
<td><tt>host:update</tt></td>
<td>Host</td>
<td>Update, Restore</td>
</tr>

<tr>
<td><tt>host:delete</tt></td>
<td>Host</td>
<td>Delete</td>
</tr>

<tr>
<td><tt>host:list</tt></td>
<td>Host</td>
<td>List host collection</td>
</tr>
</tbody>
</table><t><strong>TODO:</strong> add more scopes, such as for listing collections, process statuses, and administrative scopes.</t>
</section>
</section>

<section anchor="object-specific-authorization"><name>Object-Specific Authorization</name>
<t>An RPP process may require conveying the specific object being processed in the authorization request so that the registrant can give informed consent for that specific object. This is necessary to prevent overbroad consent where a registrant might unknowingly authorize unwanted operations on their objects. Conveying the specific object also allows the AS to enforce fine-grained access control and ensures that the registry has verifiable evidence of exactly which object was authorized.</t>
<t>OAuth 2.0 Rich Authorization Requests (RAR) <xref target="RFC9396"></xref> extends the standard OAuth 2.0 authorization request with an <tt>authorization_details</tt> parameter that carries a structured JSON object describing precisely what the client is requesting authorization for. Unlike scopes, which are coarse-grained string tokens, <tt>authorization_details</tt> allows the request to include typed, fine-grained authorization data, such as the specific object being acted upon. The AS can present this information to the user in a meaningful consent screen.</t>
<t>Table <xref target="tbl-rar"></xref> lists the RAR fields defined for RPP.</t>
<table anchor="tbl-rar"><name>RPP Transfer Authorization, RAR <tt>authorization_details</tt> object (Primary Method, <xref target="RFC9396"></xref>)</name>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Requirement</th>
<th>Description</th>
</tr>
</thead>

<tbody>
<tr>
<td><tt>type</tt></td>
<td>String</td>
<td>REQUIRED</td>
<td>The type of RPP operation being authorized.</td>
</tr>

<tr>
<td><tt>object_type</tt></td>
<td>String</td>
<td>REQUIRED</td>
<td>The type of RPP object the operation is being performed upon.</td>
</tr>

<tr>
<td><tt>object_identifier</tt></td>
<td>String</td>
<td>REQUIRED</td>
<td>The unique identifier of the specific object the operation applies to (e.g., <tt>foo.example</tt> or <tt>CID-12345</tt>).</td>
</tr>
</tbody>
</table><t>Example RAR <tt>authorization_details</tt> value for a domain transfer:</t>

<sourcecode type="json"><![CDATA[[{
  "type": "transfer",
  "object_type": "domain",
  "object_identifier": "foo.example"
}]
]]>
</sourcecode>
<t>The AS MUST echo the <tt>authorization_details</tt> back as a claim in the issued JWT. The registry MUST validate the <tt>authorization_details</tt> claim in the token and MUST verify that <tt>object_type</tt> and <tt>object_identifier</tt> match the object to which the operation is being applied.</t>
</section>

<section anchor="claims"><name>Claims</name>
<t>The JWT Profile for OAuth 2.0 Access Tokens defined in <xref target="RFC9068"></xref> defines a standard set of claims that MUST be present in every access token, such as <tt>iss</tt>, <tt>sub</tt>, <tt>aud</tt>, <tt>exp</tt>, and <tt>scope</tt>. RPP also defines additional custom claims that are specific to RPP, such as <tt>rpp_registrar_id</tt> (see <xref target="rpp-specific-claims"></xref>). These claims provide the necessary information for the RPP server to make informed access control decisions based on the identity of the requester, the registrar they represent, and the specific permissions granted by their token.</t>

<section anchor="jwt-profile-claims"><name>JWT Profile Claims</name>
<t>The JWT Profile for OAuth 2.0 Access Tokens defined in <xref target="RFC9068"></xref> specifies a standard set of claims that MUST be included in every access token issued by the AS.</t>
<t>Table <xref target="tbl-oauth-claims"></xref> lists the JWT Profile claims that MUST be present in every RPP access token:</t>
<table anchor="tbl-oauth-claims"><name>OAuth 2.0 Access Token Claims for RPP (<xref target="RFC9068"></xref>)</name>
<thead>
<tr>
<th>Claim</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>

<tbody>
<tr>
<td><tt>iss</tt></td>
<td>String (URI)</td>
<td>Identifies the issuing AS. The RPP server MUST validate this against its set of trusted issuers.</td>
</tr>

<tr>
<td><tt>sub</tt></td>
<td>String</td>
<td>The subject of the token. For machine-to-machine flows this MUST be the client identifier. For interactive flows this MUST be the end-user identifier of the authenticated end-user at the issuing AS. The end-user MAY be a registrar employee operating the registrar's management system, or a registry employee using the registry client application.</td>
</tr>

<tr>
<td><tt>aud</tt></td>
<td>String or Array</td>
<td>Identifies the intended audience. MUST include the RPP server's resource identifier. The RPP server MUST reject tokens where its own identifier is not present in this claim.</td>
</tr>

<tr>
<td><tt>exp</tt></td>
<td>Numeric date</td>
<td>Expiry time. The RPP server MUST reject tokens that have expired.</td>
</tr>

<tr>
<td><tt>iat</tt></td>
<td>Numeric date</td>
<td>Time at which the token was issued.</td>
</tr>

<tr>
<td><tt>jti</tt></td>
<td>String</td>
<td>Unique identifier for the token, used to prevent token replay attacks.</td>
</tr>

<tr>
<td><tt>client_id</tt></td>
<td>String</td>
<td>The OAuth 2.0 client identifier of the RPP client application.</td>
</tr>

<tr>
<td><tt>scope</tt></td>
<td>String</td>
<td>Space-separated list of granted scopes (see <xref target="scopes"></xref>). The RPP server MUST enforce access control based on the scopes present in this claim.</td>
</tr>
</tbody>
</table></section>

<section anchor="rpp-specific-claims"><name>RPP-Specific Claims</name>
<t>In addition to the standard JWT Profile claims defined in <xref target="RFC9068"></xref>, table <xref target="tbl-rpp-claims"></xref> lists the RPP-specific claims that are defined to enable fine-grained authorization decisions. Required claims MUST be present in every RPP access token. Optional claims SHOULD be included when applicable to the deployment or request context.</t>
<table anchor="tbl-rpp-claims"><name>RPP Specific Access Token Claims</name>
<thead>
<tr>
<th>Claim</th>
<th>Requirement</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>

<tbody>
<tr>
<td><tt>rpp_registrar_id</tt></td>
<td>REQUIRED</td>
<td>String</td>
<td>The identifier of the registrar on whose behalf the request is made. The RPP server MUST validate that this identifier matches a known and authorized registrar. This claim MUST be present in all access tokens used for RPP requests.</td>
</tr>

<tr>
<td><tt>rpp_reseller_id</tt></td>
<td>OPTIONAL</td>
<td>String</td>
<td>The identifier of the reseller acting through the registrar's client application. This claim SHOULD be included when the request originates from a reseller operating under the registrar's account. The RPP server MAY use this claim for access control, auditing, and attribution purposes. The value is interpreted within the namespace of the registrar identified by <tt>rpp_registrar_id</tt>.</td>
</tr>
</tbody>
</table><t>The combination of the <tt>sub</tt> claim and the <tt>rpp_registrar_id</tt> claim provides a complete, two-dimensional identity for every RPP request: <tt>sub</tt> identifies the individual principal (registrar employee, automated process, or registrar customer) that initiated the request, while <tt>rpp_registrar_id</tt> identifies the registrar organization as a whole within the registry's domain.</t>
<t>The identity of the <tt>sub</tt> depends on both the flow type and the identity domain of the principal:</t>

<ul spacing="compact">
<li>In <strong>machine-to-machine</strong> flows, <tt>sub</tt> is the registrar's OAuth 2.0 client identifier, representing an automated system acting on behalf of the registrar. The token is issued by the <strong>registry's AS</strong>, which maintains the registrar's client credentials.</li>
<li>In <strong>interactive flows initiated by registrar staff</strong>, <tt>sub</tt> is the identifier of the registrar employee. Registrar employees are managed as users in the <strong>registry's AS</strong>. The token is therefore also issued by the registry's AS, and the <tt>sub</tt> value is the employee's account identifier within that server. The <tt>iss</tt> claim will identify the registry's AS.</li>
<li>In <strong>interactive flows initiated by a registrant customer</strong>, the situation is different. Registrant customers are not managed in the registry's AS, they are maintained in the <strong>registrar's own AS</strong> (the registrar acts as the AS for its customers). The token is therefore issued by the registrar's AS, and the <tt>iss</tt> claim will identify the registrar's AS as the issuer. The registry MUST have a pre-established trust relationship with the registrar's AS to accept and validate such tokens. In this case, the <tt>sub</tt> value MUST be the registrant's identifier as it exists in the registry database. The registrar MUST use this registry-assigned id, not any registrar-internal customer identifier, as the <tt>sub</tt> value. This ensures the registry can unambiguously correlate the token's subject to an existing provisioned contact object. This enables verification of ownership and consent for operations. The registry MUST reject tokens where the <tt>sub</tt> value does not match a known contact handle associated with the object being acted upon.</li>
</ul>
<t>Extensions and profiles MAY define additional claims. All additional claims MUST use a URI or a collision-resistant name as the claim name to prevent conflicts with registered claims.</t>
</section>

<section anchor="claim-validation"><name>Claim Validation</name>
<t>The RPP server MUST validate all required claims in accordance with <xref target="RFC9068"></xref> and <xref target="RFC8725"></xref>.</t>
</section>
</section>

<section anchor="data-objects"><name>Data Objects</name>
<t>The RPP Data Object Catalog described in <xref target="I-D.ietf-rpp-data-objects"></xref> is extended to include new objects required for using OAuth 2.0 as a framework for authorization in RPP.</t>

<ul spacing="compact">
<li><t><em>Client Object</em>: A registrar MUST register at least one OAuth 2.0 client to interact with the RPP server. The Client Object MUST include the following attributes:</t>

<ul spacing="compact">
<li>Name: Unique (in registrar namespace) name of application.</li>
<li>Description: A brief description of the application's purpose.</li>
<li>Redirect URL: The URL to which the authorization server will redirect the user after granting or denying access.</li>
<li>Client Id: The OAuth 2.0 client identifier issued to the client during the registration process.</li>
<li>Client Secret: The OAuth 2.0 client secret issued to the client during the registration process.</li>
</ul></li>
<li>TODO</li>
</ul>
</section>

<section anchor="federation"><name>Federation</name>
<t>For more advanced use cases, enabled by OAuth 2.0, such as an interactive federated object transfer, it is necessary for the RPP server to validate tokens issued by external ASs operated by registrars. This requires the RPP server to establish trust with these external ASs. When JWTs are used for Client Authentication as specified in <xref target="RFC7523"></xref>, the registrar MUST be able to manage their public key(s) in the registry database.</t>
</section>

<section anchor="flows"><name>Flows</name>
<t>RPP defines two distinct authorization flows: machine-to-machine flows and interactive flows. Machine-to-machine flows are designed for use in automated systems where no user interaction is required. Interactive flows are designed for use in scenarios where end-user interaction is required, such as when a registrant employee needs to interact with the registry system.
For these interactive flows, the OAuth 2.0 Authorization Code grant <xref target="RFC6749" sectionFormat="bare" section="Section 4.1"></xref> MUST be used.</t>

<section anchor="machine-to-machine"><name>Machine to Machine</name>
<t>The machine-to-machine (M2M) flow is used for automated RPP requests such as domain provisioning, renewal, or host management sent by a registrar's backend systems to the registry. No end-user interaction is involved. JWTs for Client Authentication as specified in <xref target="RFC7523"></xref> or the OAuth 2.0 Client Credentials grant <xref target="RFC6749" sectionFormat="bare" section="Section 4.4"></xref> MUST be used.</t>
<t>In this flow the registrar's system authenticates directly with the registry's AS using a signed JWT or a pre-registered <tt>client_id</tt> and <tt>client_secret</tt>. The AS issues a short-lived access token scoped to the requested RPP operations. The registrar's system then includes this token in the <tt>Authorization</tt> header of each RPP request sent to the registry.</t>
<t>The <tt>sub</tt> claim in the resulting token MUST be set to the <tt>client_id</tt> of the registrar's system. The <tt>rpp_registrar_id</tt> claim MUST also be present, identifying the registrar organization within the registry's namespace.</t>
<figure><name>OAuth 2.0 Client Credentials Flow for Registrar-to-Registry Requests
</name>
<sourcecode type="ascii"><![CDATA[  Registrar                  Registry             Registry
  Backend                    Auth Server          RPP Server
     |                           |                    |
     | 1. Token request          |                    |
     |  (client_id +             |                    |
     |   client_secret           |                    |
     |   + scope)                |                    |
     +-------------------------->|                    |
     |                           |                    |
     | 2. Access token (JWT)     |                    |
     |<--------------------------|                    |
     |                           |                    |
     | 3. RPP request            |                    |
     |  (Authorization:          |                    |
     |   Bearer <token>)         |                    |
     +----------------------------------------------->|
     |                           |                    |
     |                           |  4. Validate JWT   |
     |                           |  (verify signature |
     |                           |   using cached     |
     |                           |   public key,      |
     |                           |   check claims     |
     |                           |   and scopes)      |
     |                           |                    |
     | 5. RPP response           |                    |
     |<-----------------------------------------------|
     |                           |                    |
]]>
</sourcecode>
</figure>
<t>The steps in the diagram are as follows:</t>

<ol spacing="compact">
<li>The registrar's backend system sends a token request to the registry's AS, it SHOULD use JWTs for Client Authentication as specified in <xref target="RFC7523"></xref> or if this is not supported by the AS, it SHOULD use the Client Credentials Grant, and the requested RPP scopes (e.g., <tt>domain:create</tt>).</li>
<li>The AS validates the client credentials and issues a signed, short-lived JWT access token containing the granted scopes, <tt>sub</tt> (set to <tt>client_id</tt>), and <tt>rpp_registrar_id</tt>.</li>
<li>The registrar's system sends the RPP request to the registry's RPP server, including the access token in the HTTP <tt>Authorization</tt> header as a Bearer token.</li>
<li>The RPP server validates the JWT entirely locally without contacting the AS. It verifies the token's signature using the AS's public key, checks the standard claims (<tt>iss</tt>, <tt>aud</tt>, <tt>exp</tt>), and confirms that the <tt>scope</tt> claim includes the scope required for the requested operation.</li>
<li>If validation succeeds, the RPP server processes the request and returns the RPP response.</li>
</ol>
<t>Example request using JWT Client Authentication (<xref target="RFC7523"></xref>), using the <tt>domain:create</tt> scope. The client authenticates by presenting a signed JWT assertion instead of a client secret:</t>

<sourcecode type="http"><![CDATA[POST /token HTTP/2
Host: as.rpp.example
Content-Type: application/x-www-form-urlencoded

&scope=domain%3Acreate
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiI[...omitted for brevity...]
]]>
</sourcecode>
<t>The <tt>client_assertion</tt> is a JWT signed with the registrar's private key. Its payload MUST contain:</t>

<ul spacing="compact">
<li><tt>iss</tt>: the registrar's <tt>client_id</tt></li>
<li><tt>sub</tt>: the registrar's <tt>client_id</tt></li>
<li><tt>aud</tt>: the registry AS token endpoint URI</li>
<li><tt>jti</tt>: a unique identifier for this assertion (to prevent replay)</li>
<li><tt>exp</tt>: expiry time (SHOULD be short-lived, e.g., 60 seconds)</li>
</ul>
<t>Example <tt>client_assertion</tt> payload:</t>

<sourcecode type="json"><![CDATA[{
  "iss": "registrar-client-id",
  "sub": "registrar-client-id",
  "aud": "https://authorization-server.rpp.example/token",
  "jti": "unique-jwt-id-123",
  "exp": 1746134400
}
]]>
</sourcecode>
<t>Example request using the OAuth 2.0 Client Credentials grant with a <tt>client_secret</tt> (fallback when JWT Client Authentication is not supported):</t>

<sourcecode type="http"><![CDATA[POST /token HTTP/2
Host: authorization-server.rpp.example
Authorization: Basic cmVnaXN0cmFyLWNsaWVudC1pZDpjbGllbnQtc2VjcmV0
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&scope=domain%3Acreate
]]>
</sourcecode>
<t>Response:</t>

<sourcecode type="http"><![CDATA[HTTP/2 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "domain:create"
}
]]>
</sourcecode>

<section anchor="high-risk-operations"><name>High-Risk Operations</name>
<t>The machine-to-machine (M2M) Client Credentials flow is appropriate for routine automated provisioning, but certain high-risk operations, e.g. object transfer or modification of authorisation information, MUST require proof that an authorized human principal explicitly approved the action. Without enforcement, a registrar could use M2M tokens for all operations, eliminating individual accountability. The operations for which interactive authentication is required are a matter of registry policy.</t>
<t>The following mechanisms MAY be used by the registry to enforce interactive authentication for designated operations:</t>
<t><strong><tt>sub</tt> MUST identify a human principal</strong>: The registry MAY require that for high-risk operations, the <tt>sub</tt> claim MUST contain the identifier of an authenticated human principal and MUST NOT equal the <tt>client_id</tt>. In M2M tokens issued via the Client Credentials grant, <tt>sub</tt> is always set to <tt>client_id</tt>, representing an automated system rather than a human. By mandating <tt>sub</tt> != <tt>client_id</tt> for designated operations, the registry ensures those operations can only be performed with a token issued on behalf of a real, identified individual. The RPP server MUST reject requests for these operations when <tt>sub</tt> equals <tt>client_id</tt>.</t>
<t><strong>Scope restriction by grant type</strong>: The registry's AS SHOULD be configured to refuse issuing certain high-risk scopes to the Client Credentials grant type. Only the Authorization Code grant (interactive) MAY be permitted to obtain these scopes. This prevents a registrar from obtaining the necessary scope for a high-risk operation through unattended M2M authentication.</t>
</section>
</section>

<section anchor="interactive"><name>Interactive</name>
<t>The interactive flow is used for RPP requests that require end-user interaction. The OAuth 2.0 Authorization Code grant <xref target="RFC6749" sectionFormat="bare" section="Section 4.1"></xref> MUST be used for this flow. <strong>Registrar employees</strong> are managed as users in the <strong>registry's AS</strong>. A registrar employee uses the registrar's client application to perform operations on behalf of the registrar, such as updating domain records or managing contacts. The registry's AS authenticates the employee and issues an access token. The <tt>sub</tt> claim will contain the employee's account identifier in the registry's AS, and the <tt>iss</tt> claim will identify the registry's AS.</t>
<t>This enables a registrar to implement fine-grained access control for its employees by assigning different scopes to different employee accounts in the registry's AS. For example, a junior employee may be granted only <tt>domain:read</tt> scope, while a senior employee may be granted <tt>domain:create</tt> and <tt>domain:update</tt> scopes. Support for this flow is OPTIONAL; a registrar MAY use the M2M flow for all operations if individual employee accountability is not required.</t>
<t>In this flow, the employee authenticates with the registry's AS. The registry acts as both the AS and the RPP resource server.</t>
<figure><name>Interactive Flow - Registrar Employee
</name>
<sourcecode type="ascii"><![CDATA[  Registrar        Registrar          Registry             Registry
  Employee         Client App         Auth Server          RPP Server
  (Browser)            |                  |                    |
     | 1. Login /      |                  |                    |
     |  auth request   |                  |                    |
     +---------------->|                  |                    |
     |                 |                  |                    |
     |                 | 2. Forward auth  |                    |
     |                 |  request         |                    |
     |                 +----------------->|                    |
     |                 |                  |                    |
     |                 | 3. Access token  |                    |
     |                 |  (sub=employee_id|                    |
     |                 |   iss=registry)  |                    |
     |                 |<-----------------|                    |
     |                 |                  |                    |
     | 4. Access token |                  |                    |
     |<----------------|                  |                    |
     |                 |                  |                    |
     | 5. RPP request  |                  |                    |
     +---------------->|                  |                    |
     |                 |                  |                    |
     |                 | 6. RPP request   |                    |
     |                 |  (Bearer token)  |                    |
     |                 +-------------------------------------->|
     |                 |                  |                    |
     |                 |                  |  7. Validate JWT   |
     |                 |                  |  (local, cached    |
     |                 |                  |   registry public  |
     |                 |                  |   key)             |
     |                 |                  |                    |
     |                 | 8. RPP response  |                    |
     |                 |<--------------------------------------|
     |                 |                  |                    |
     | 9. RPP response |                  |                    |
     |<----------------|                  |                    |
     |                 |                  |                    |
]]>
</sourcecode>
</figure>
<t>The steps in the diagram are as follows:</t>

<ol spacing="compact">
<li>The registrar employee initiates a login or authorization request using the registrar's client application.</li>
<li>The client application forwards the authorization request to the registry's AS using the OAuth 2.0 Authorization Code grant.</li>
<li>The registry's AS authenticates the employee and issues a signed, short-lived JWT access token containing the granted scopes, <tt>sub</tt> (set to the employee's account identifier), and <tt>rpp_registrar_id</tt>. The <tt>iss</tt> claim identifies the registry's AS.</li>
<li>The client application returns the access token to the registrar employee.</li>
<li>The registrar employee submits an RPP request via the client application.</li>
<li>The client application forwards the RPP request to the registry's RPP server, including the access token in the HTTP <tt>Authorization</tt> header as a Bearer token.</li>
<li>The RPP server validates the JWT locally using the cached registry public key (fetched via OAuth 2.0 AS Metadata <xref target="RFC8414"></xref> and the referenced JWKS <xref target="RFC7517"></xref> endpoint). It verifies the signature, checks the standard claims (<tt>iss</tt>, <tt>aud</tt>, <tt>exp</tt>), and confirms the <tt>scope</tt> claim includes the scope required for the requested operation.</li>
<li>The RPP server processes the request and returns the RPP response to the client application.</li>
<li>The client application returns the RPP response to the registrar employee.</li>
</ol>

<section anchor="example"><name>Example</name>
<t><strong>Step 2 — Authorization Request</strong> (browser redirect to Registry AS):</t>

<artwork><![CDATA[GET /authorize
    ?response_type=code
    &client_id=registrar-app-client
    &redirect_uri=https%3A%2F%2Fclient.registrar.example%2Fcallback
    &scope=domain%3Acreate%20domain%3Aupdate
    &state=af0ifjsldkj
    &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
    &code_challenge_method=S256
Host: as.registry.example
]]>
</artwork>
<t><strong>Step 2 — Authorization Response</strong> (redirect back to client):</t>

<artwork><![CDATA[HTTP/1.1 302 Found
Location: https://client.registrar.example/callback
          ?code=SplxlOBeZQQYbYS6WxSbIA
          &state=af0ifjsldkj
]]>
</artwork>
<t><strong>Token Request</strong> (client exchanges authorization code for access token):</t>

<artwork><![CDATA[POST /token HTTP/1.1
Host: as.registry.example
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient.registrar.example%2Fcallback
&client_id=registrar-app-client
&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
]]>
</artwork>
<t><strong>Token Response</strong>:</t>

<artwork><![CDATA[HTTP/1.1 200 OK
Content-Type: application/json

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "domain:create domain:update"
}
]]>
</artwork>
<t>The decoded JWT access token payload will contain claims similar to:</t>

<sourcecode type="json"><![CDATA[{
  "iss": "https://as.registry.example",
  "sub": "employee-42@registrar.example",
  "aud": "https://rpp.registry.example",
  "exp": 1746134400,
  "iat": 1746130800,
  "scope": "domain:create domain:update",
  "rpp_registrar_id": "REGISTRAR-001"
}
]]>
</sourcecode>
<t><strong>Step 6 — RPP Request</strong> (client sends RPP request with Bearer token):</t>

<artwork><![CDATA[GET /rpp/v1/domains/foo.example HTTP/1.1
Host: rpp.registry.example
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

]]>
</artwork>
<t><strong>RPP Response</strong>:</t>

<artwork><![CDATA[HTTP/1.1 200 OK
Content-Type: application/json

{
  "name": "foo.example",
  ...
}
]]>
</artwork>
</section>
</section>
</section>

<section anchor="iana-considerations"><name>IANA Considerations</name>
<t>TODO</t>
</section>

<section anchor="internationalization-considerations"><name>Internationalization Considerations</name>
<t>TODO</t>
</section>

<section anchor="security-considerations"><name>Security Considerations</name>
<t>TODO</t>
</section>

<section anchor="privacy-considerations"><name>Privacy Considerations</name>
<t>TODO</t>
</section>

<section anchor="change-history"><name>Change History</name>
<t>TODO</t>

<section anchor="version-00"><name>Version 00</name>

<ul spacing="compact">
<li>Created initial draft with core concepts and flows.</li>
</ul>
</section>
</section>

</middle>

<back>
<references><name>Normative References</name>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.ietf-rpp-core.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml3/reference.I-D.ietf-rpp-data-objects.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3986.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6749.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6750.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7517.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7519.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7523.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7617.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7636.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8414.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8725.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9068.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9396.xml"/>
</references>

<section anchor="acknowledgements" numbered="false"><name>Acknowledgements</name>
<t>TODO</t>
</section>

</back>

</rfc>
