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


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

]>


<rfc ipr="trust200902" docName="draft-lopresti-open-cloud-mesh-06" category="std" consensus="true" submissionType="IETF">
  <front>
    <title>Open Cloud Mesh</title>

    <author initials="G." surname="Lo Presti" fullname="Giuseppe Lo Presti">
      <organization>CERN</organization>
      <address>
        <email>giuseppe.lopresti@cern.ch</email>
        <uri>http://cern.ch/lopresti</uri>
      </address>
    </author>
    <author initials="M. B." surname="de Jong" fullname="Michiel de Jong">
      <organization>Ponder Source</organization>
      <address>
        <email>michiel@pondersource.org</email>
        <uri>https://pondersource.com</uri>
      </address>
    </author>
    <author initials="M." surname="Baghbani" fullname="Mahdi Baghbani">
      <organization>Ponder Source</organization>
      <address>
        <email>mahdi@pondersource.org</email>
        <uri>https://pondersource.com</uri>
      </address>
    </author>
    <author initials="M." surname="Nordin" fullname="Micke Nordin">
      <organization>SUNET</organization>
      <address>
        <email>kano@sunet.se</email>
        <uri>https://code.smolnet.org/micke</uri>
      </address>
    </author>

    <date year="2025" month="October" day="02"/>

    <area>Security</area>
    
    <keyword>Internet-Draft</keyword>

    <abstract>


<?line 38?>

<t>Open Cloud Mesh (OCM) is a server federation protocol that is used to
notify a Receiving Party that they have been granted access to some
Resource.  It has similarities with authorization flows such as
OAuth, as well as with social internet protocols such as ActivityPub
and email.</t>

<t>A core use case of OCM is when a user (e.g., Alice on System A) wishes
to share a resource (e.g., a file) with another user (e.g., Bob on
System B) without transferring the resource itself or requiring Bob to
log in to System A.</t>

<t>While this scenario is illustrative, OCM is designed to support a
broader range of interactions, including but not limited to file
transfers.</t>

<t>Open Cloud Mesh handles interactions only up to the point where the
Receiving Party is informed of their access to the Resource.  Actual
Resource access is subsequently managed by other protocols, such as
WebDAV.</t>



    </abstract>



  </front>

  <middle>


<?line 60?>

<section anchor="introduction"><name>Introduction</name>

<t>Open Cloud Mesh was initially conceived of in 2015 and has been deployed
since 2016.  OCM has been implemented by several platforms, including
CERNBox, Nextcloud, OpenCloud, ownCloud, and Seafile.</t>

<t>The goal of OCM is to provide a secure, scalable, and flexible
infrastructure for securely sharing and collaborating on resources and
has seen wide adoption, not least in the academic sector.</t>

<t>The core idea of OCM is to make it simple for users to do the right
thing.  This is achieved by providing a protocol that abstracts away
security and authentication details from the users to the servers acting
on behalf of the users.  Another important point of the protocol is the
invitation mechanism that lets users connect over established human
relationships and uses those connections to establish contact between
their respective OCM servers.</t>

</section>
<section anchor="terms"><name>Terms</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 [RFC2119] [RFC8174] when, and only when,
they appear in all capitals, as shown here.</t>

<t>We define the following concepts, with some non-normative references to
related concepts from OAuth [RFC6749] and elsewhere:</t>

<t><list style="symbols">
  <t><strong>Resource</strong> - The piece of data or interaction to which access is
being granted, including but not limited to: a file or folder, a video
call, a contact, a printer queue, etc.</t>
  <t><strong>Remote Resource</strong> - A Resource provided by the Sending Server.</t>
  <t><strong>Shared Resource</strong> - A Resource shared by an OCM Server, becoming a
Remote Resource if accepted by the Invite Receiver OCM Server.</t>
  <t><strong>Share</strong> - A policy rule stating that certain actors have specific
access rights to a Resource; it MAY also refer to a record in a
database representing this rule.</t>
  <t><strong>Sending Party</strong> - A person or party who is authorized to create
Shares; similar to "Resource Owner" in OAuth [RFC6749], identified by
its OCM Address.</t>
  <t><strong>Receiving Party</strong> - A person, group or party who is granted access
to the Resource through the Share; similar to "Requesting Party / RqP"
in OAuth-UMA, identified by its OCM Address.</t>
  <t><strong>Share Creation Notification</strong> - A server-to-server request from the
sending server to the receiving server, notifying the receiving server
that a Share has been created.</t>
  <t><strong>Sending Server</strong> - The server that:
  <list style="symbols">
      <t>holds the Resource ("file server" or "Entreprise File Sync and Share
(EFSS) server" role),</t>
      <t>provides access to it (by exposing at least one "API"),</t>
      <t>takes the decision to create the Share based on user interface
gestures from the Sending Party (the "Authorization Server" role in
OAuth [RFC6749]),</t>
      <t>takes the decision about authorizing attempts to access the Resource
(the "Resource Server" role in OAuth [RFC6749]),</t>
      <t>sends out Share Creation Notifications when appropriate (see below).</t>
    </list></t>
  <t><strong>Receiving Server</strong> - The server that:
  <list style="symbols">
      <t>receives Share Creation Notifications (see below),</t>
      <t>actively or passively notifies the receiving user or group of any
incoming Share Creation Notification,</t>
      <t>acts as an API client, allowing the receiving user to access the
Resource through an API (e.g., WebDAV [RFC4918]) of the sending
server.</t>
    </list></t>
  <t><strong>Sending Gesture</strong> - A user interface interaction from the Sending
Party to the Sending Server, conveying the intention to create a
Share.</t>
  <t><strong>Share Creation</strong> - The addition of a Share to the database state of
the Sending Server, in response to a successful Sending Gesture or for
another reason.</t>
  <t><strong>Sharing User</strong> - A user providing access to a Resource through a
Share.</t>
  <t><strong>FQDN</strong> - Fully Qualified Domain Name, such as <spanx style="verb">"cloud.example.com"</spanx>.</t>
  <t><strong>OCM Server</strong> - A server that supports OCM.</t>
  <t><strong>OCM API Discovery</strong> - Process of evaluating properties of a Remote
Resource, after establishing contact with an OCM Server.</t>
  <t><strong>Discovering Server</strong> - A server that tries to obtain information in
OCM API Discovery.</t>
  <t><strong>Discoverable Server</strong> - A server that tries to supply information in
OCM API Discovery.</t>
  <t><strong>OCM Address</strong> - identifies a user or group "at" an OCM Server.
The OCM Address contains a server specific Party identifier, a host
locating the OCM Server and an optional port. The OCM Address is not a
URI as it does not have scheme and the identifier may contain reserved
characters.  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
  ocm-address = identifier "@" host [ ":" port]
]]></artwork></figure>
  <vspace blankLines='1'/>
The identifier is an opaque, case-sensitive UTF-8 string. It is 
  separated from the host by the last "@" in the OCM Address. It is
  possible to have multiple @-signs in a OCM-address, e.g. when an 
  email address is the local part of the address like 
  <spanx style="verb">nomen.nescio@example.org@ocm.example.org</spanx>.  <vspace blankLines='1'/>
host is an IP literal encapsulated within square brackets, an IPv4 
  address in dotted decimal form, or a registered name as described in
  [RFC3986].  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
  host = IP-literal / IPv4address / reg-name
]]></artwork></figure>
  <vspace blankLines='1'/>
The optional port subcomponent can be used to specify a port to use
  for discovery (see Discovery Process).  <vspace blankLines='1'/>
The OCM Server MUST be discoverable at the given host and optional 
  port via the Well-Known [RFC8615] path <spanx style="verb">/.well-known/ocm</spanx>. The OCM 
  Address MUST NOT contain a path.</t>
  <t><strong>OCM Notification</strong> - A message from the Receiving Server to the
Sending Server or vice versa, using the OCM Notifications endpoint.</t>
  <t><strong>Invite Message</strong> - Out-of-band message used to establish contact
between parties and servers in the Invite Flow, containing an Invite
Token (see below) and the Invite Sender's OCM Address.</t>
  <t><strong>Invite Sender</strong> - The party sending an Invite, identified by its
OCM Address.</t>
  <t><strong>Invite Receiver</strong> - The party receiving an Invite, identified by its
OCM Address.</t>
  <t><strong>Invite Sender OCM Server</strong> - The server holding an address book
used by the Invite Sender, to which details of the Invite Receiver are
to be added.</t>
  <t><strong>Invite Receiver OCM Server</strong> - The server holding an address book
used by the Invite Receiver, to which details of the Invite Sender are
to be added.</t>
  <t><strong>Invite Token</strong> - A hard-to-guess string used in the Invite Flow,
generated by the Invite Sender OCM Server and linked uniquely to the
Invite Sender's OCM Address.</t>
  <t><strong>Invite Creation Gesture</strong> - Gesture from the Invite Sender to the
Invite Sender OCM Server, resulting in the creation of an Invite
Token.</t>
  <t><strong>Invite Acceptance Gesture</strong> - Gesture from the Invite Receiver to
the Invite Receiver OCM Server, supplying the Invite Token as well as
the OCM Address of the Invite Sender, effectively allowlisting the
Invite Sender OCM Server for sending Share Creation Notifications to
the Invite Receiver OCM Server.</t>
  <t><strong>Invite Acceptance Request</strong> - API call from the Invite Receiver OCM
Server to the Invite Sender OCM Server, supplying the Invite Token as
well as the OCM Address of the Invite Receiver, effectively
allowlisting the Invite Sender OCM Server for sending Share Creation
Notifications to the Invite Receiver OCM Server.</t>
  <t><strong>Invite Acceptance Response</strong> - HTTP response to the Invite
Acceptance Request.</t>
  <t><strong>Share Name</strong> - A human-readable string, provided by the Sending
Party or the Sending Server, to help the Receiving Party understand
which Resource the Share grants access to.</t>
  <t><strong>Share Permissions</strong> - protocol-specific allowances granted to the
Receiving Party on the modes of accessing the Resource.</t>
  <t><strong>Share Requirements</strong> - Protocol-specific restrictions on the modes
of accessing the Resource.</t>
  <t><strong>WAYF Page</strong> - A Where-Are-You-From page is a discovery service used
to identify the OCM Server of an Invite Receiver.</t>
  <t><strong>Directory Service</strong> - A third-party service that exposes a list of
trusted OCM Servers.</t>
</list></t>

</section>
<section anchor="general-flow"><name>General Flow</name>

<t>The lifecycle of an Open Cloud Mesh Share starts with prerequisites such
as establishing trust, establishing contact, and OCM API Discovery.</t>

<t>Then the share creation involves the Sending Party making a Sending
Gesture to the Sending Server, the Sending Server carrying out the
actual Share Creation, and the Sending Server sending a Share Creation
Notification to the Receiving Server.</t>

<t>After this, the Receiving Server MAY notify the Receiving Party and/or
the Sending Server, and will act as an API client through which the
Receiving Party can access the Resource.  The Receiving Party or
the Sending Party MAY then update or delete the Share: the respective
Server MAY send a Notification to the other party about the change.</t>

</section>
<section anchor="establishing-contact"><name>Establishing Contact</name>

<t>Before the Sending Server can send a Share Creation Notification to the
Receiving Server, it MUST establish the Receiving Party's OCM
Address (containing the Receiving Server's FQDN, and the Receiving
Party's identifier), among other things.  Some steps may preceed the
Sending Gesture, allowing the Sending Party to establish (with some
level of trust) the OCM Address of the Receiving Party.  In other cases,
establishing the OCM Address of the Receiving Party happens as part of
the Sending Gesture.</t>

<section anchor="direct-entry"><name>Direct Entry</name>

<t>The simplest way for this is if the Receiving Party shares their OCM
Address with the Sending Party through some out-of-band means, and the
Sending Party enters this string into the user interface of the Sending
Server, by means of typing or pasting into an HTML form, or clicking a
link to a URL that includes the string in some form.</t>

</section>
<section anchor="address-books"><name>Address books</name>

<t>The Sending Server MAY offer the Sending Party an address book tool,
where OCM Addresses can be stored over time in a labeled and/or
searchable way.  This decouples the act by which the OCM Address string
is passed into the Sending Server's database from the selection of the
Receiving Party in preparation for Share Creation.</t>

</section>
<section anchor="public-link-flow"><name>Public Link Flow</name>

<t>An interface for anonymously viewing a Resource on the Sending Server
MAY allow any internet user to type or paste an OCM address into an HTML
form, as a Sending Gesture.  This means that the Sending Party and the
Receiving Party could be the same person, so contact between them does
not need to be explicitly established.</t>

</section>
<section anchor="public-invite-flow"><name>Public Invite Flow</name>

<t>Similarly, an interface on the Sending Server MAY allow any internet
user to type or paste an OCM address into an HTML form, as a Sending
Gesture for a given Resource, without itself providing a way to access
that particular Resource.  A link to this interface could then for
instance be shared on a mailing list, allowing all subscribers to
effectively request access to the Resource by making a Sending Gesture
to the Sending Server with their own OCM Address.</t>

</section>
<section anchor="invite-flow"><name>Invite Flow</name>

<section anchor="rationale"><name>Rationale</name>

<t>Many methods for establishing contact allow unsolicited contact with the
prospective Receiving Party whenever that party's OCM Address is known.
The Invite Flow requires the Receiving Party to explicitly accept it
before it can be used, which establishes bidirectional trust between the
two parties involved.</t>

<t>OCM Servers MAY enforce a policy to only accept Shares between such
trusted contacts, or MAY display a warning to the Receiving Party when a
Share Creation Notification from an unknown Sending Party is received</t>

</section>
<section anchor="steps"><name>Steps</name>

<t><list style="symbols">
  <t>the Invite Sender OCM Server generates a unique Invite Token and helps
the Invite Sender to create the Invite Message</t>
  <t>the Invite Sender uses some out-of-band communication to send the
Invite Message, containing the Invite Token and the Invite Sender OCM
Server FQDN, to the Invite Receiver</t>
  <t>the Invite Receiver navigates to the Invite Receiver OCM Server and
makes the Invite Acceptance Gesture.  This step MAY be facilitated if
the Invite Sender OCM Server implements a WAYF Page, such that the
Invite Message would include a link to it for the Invite Receiver to
navigate to: the Invite Receiver would then be able to indicate their
OCM Server and proceed with the Invite Acceptance Gsture without
manually copying the Invite Token.</t>
  <t>the Invite Receiver OCM Server discovers the OCM API of the Invite
Sender OCM Server using generic OCM API Discovery (see section below)</t>
  <t>the Invite Receiver OCM Server sends the Invite Acceptance Request to
the Invite Sender OCM Server</t>
</list></t>

</section>
<section anchor="invite-acceptance-request-details"><name>Invite Acceptance Request Details</name>

<t>Whereas the precise syntax of the Invite Message and the Invite
Acceptance Gesture will differ between implementations, the Invite
Acceptance Request SHOULD be a HTTP POST request:</t>

<t><list style="symbols">
  <t>to the <spanx style="verb">/invite-accepted</spanx> path in the Invite Sender OCM Server's OCM
API</t>
  <t>using <spanx style="verb">application/json</spanx> as the <spanx style="verb">Content-Type</spanx> HTTP request header</t>
  <t>its request body containing a JSON document representing an object
with the following string fields:
  <list style="symbols">
      <t>REQUIRED: <spanx style="verb">recipientProvider</spanx> - FQDN of the Invite Receiver OCM
Server.</t>
      <t>REQUIRED: <spanx style="verb">token</spanx> - The Invite Token.  The Invite Sender OCM Server
SHOULD recall which Invite Sender OCM Address this token was linked
to.</t>
      <t>REQUIRED: <spanx style="verb">userID</spanx> - The Invite Receiver's identifier at their OCM
Server.</t>
      <t>REQUIRED: <spanx style="verb">email</spanx> - Non-normative / informational; an email address
for the Invite Receiver.  Not necessarily at the same FQDN as their
OCM Server.</t>
      <t>REQUIRED: <spanx style="verb">name</spanx> - Human-readable name of the Invite Receiver, as a
suggestion for display in the Invite Sender's address book</t>
    </list></t>
  <t>using TLS</t>
  <t>using httpsig [RFC9421]</t>
</list></t>

<t>The Invite Receiver OCM Server SHOULD apply its own policies for
trusting the Invite Sender OCM Server before making the Invite
Acceptance Request.</t>

<t>Since the Invite Flow does not require either Party to type or remember
the <spanx style="verb">userID</spanx>, this string does not need to be human-memorable.  Even if
the Invite Receiver has a memorable username at the Invite Receiver OCM
Server, this <spanx style="verb">userID</spanx> that forms part of their OCM Address does not need
to match it.</t>

<t>Also, a different <spanx style="verb">userID</spanx> could be given out to each contact, to avoid
correlation of identities.</t>

<t>If the Invite Sender OCM Server implements a WAYF Page, such a page MAY
include a fixed list of servers, in addition to, or instead of, a
free-text input where any OCM Server can be entered.  This is especially
useful if the Invite Sender is part of a federation of associated OCM
Servers.  In order to populate the list of associated OCM Servers, the
Invite Sender's server MAY make use of a Directory Service, which is
expected to follow the specification detailed in Appendix C.</t>

<t>Implementors that provide a WAYF Page SHOULD make the URL for the API
endpoint of such a Directory Service configurable, allowing the OCM
Server to be part of a network of associated OCM Servers.  The
configuration mechanism MAY allow an OCM Server to be part of multiple
networks, thus displaying a union of multiple lists in its WAYF Page.</t>

</section>
<section anchor="invite-acceptance-response-details"><name>Invite Acceptance Response Details</name>

<t>The Invite Acceptance Response SHOULD be a HTTP response:</t>

<t><list style="symbols">
  <t>in response to the Invite Acceptance Request</t>
  <t>using <spanx style="verb">application/json</spanx> as the <spanx style="verb">Content-Type</spanx> HTTP response header</t>
  <t>its response body containing a JSON document representing an object
with the following string fields:
  <list style="symbols">
      <t>REQUIRED: <spanx style="verb">userID</spanx> - the Invite Sender's identifier at their OCM
Server</t>
      <t>REQUIRED: <spanx style="verb">email</spanx> - non-normative / informational; an email address
for the Invite Sender.  Not necessarily at the same FQDN as their
OCM Server</t>
      <t>REQUIRED: <spanx style="verb">name</spanx> - human-readable name of the Invite Sender, as a
suggestion for display in the Invite Receiver's address book</t>
    </list></t>
</list></t>

<t>A 200 response status means the Invite Acceptance Request was
successful.
A 400 response status means the Invite Token is invalid or does not
exist.
A 403 response status means the Invite Receiver OCM Server is not
trusted to accept this Invite.
A 409 response status means the Invite was already accepted.</t>

<t>The Invite Sender OCM Server SHOULD verify the HTTP Signature on the
Invite Acceptance Request and apply its own policies for trusting the
Invite Receiver OCM Server before processing the Invite Acceptance
Request and sending the Invite Acceptance Response.</t>

<t>As with the <spanx style="verb">userID</spanx> in the Invite Acceptance Request, the one in the
Response also doesn't need to be human-memorable, doesn't need to match
the Invite Sender's username at their OCM Server.</t>

</section>
<section anchor="addition-into-address-books"><name>Addition into address books</name>

<t>Following these step, both servers MAY display the <spanx style="verb">name</spanx> of the other
party as a trusted or allowlisted contact, and enable selecting them as
a Receiving Party.  OCM Servers MAY enforce a policy to only accept
Share Creation Notifications from such trusted contacts, or MAY display
a warning to users when a Share Creation Notification from an unknown
party is received.</t>

<t>Both servers MAY also allowlist each other as a server with which at
least one of their users wishes to interact.</t>

<t>Note that Invites act symmetrically, so once contact has been
established, both the Invite Sender and the Invite Receiver MAY take on
either the Sending Party or the Receiving Party role in subsequent
Share Creation events.</t>

<t>Both parties MAY delete the other party from their address book at any
time without notifying them.</t>

</section>
<section anchor="security-advantages"><name>Security Advantages</name>

<t>It is important to underscore the value of the Invite in this scenario,
as it provides four important security advantages.  First of all, if the
Receiving Server blocks Share Creation Notifications from Sending
Parties who are not in the address book of the Receiving Party, then
this protects the Receiving Party from receiving unsolicited Shares.  An
attacker could still send the Receiving Party an unsolicited Share, but
they would first need to convince the Receiving Party through an
out-of-band communication channel to accept their invite.  In many use
cases, the Receiving Party has had other forms of contact with the
Sending Party (e.g., in-person or email back-and-forth).  The
out-of-band Invite Message thus leverages the filters and context which
the Receiving Party may already benefit from in that out-of-band
communication.  For instance, a careful Receiving Party MAY choose to
only accept Invites that reach them via a private or moderated
messaging platform.</t>

<t>Second, when the Receiving Party accepts the Invite, the Receiving
Server knows that the Sending Server they are about to interact with is
trusted by the Sending Party, which in turn is trusted by the Receiving
Party, which in turn is trusted by them.  In other words, one of their
users is requesting the allowlisting of a server they wish to interact
with, in order to interact with a party they know out-of-band.  This
gives the Receiving Server reason to put more trust in the Sending
Server than it would put into an arbitrary internet-hosted server.</t>

<t>Third, equivalently, the Sending Server knows it is essentially
registering the Receiving Server as an API client at the request of the
Receiving Party, to whom the right to request this has been traceably
delegated by the Sending Party, which is one of its registered users.</t>

<t>Fourth, related to the second one, it removes the partial 'open relay'
problem that exists when the Sending Server is allowed to include any
Receiving Server FQDN in the Sending Gesture.  Without the use of
Invites, a Distributed Denial of Service attack could be organised if
many internet users collude to flood a given OCM Server with Share
Creation Notifications which will be hard to distinguish from
legitimate requests without human interaction.  An unsolicited (invalid)
Invite Acceptance Request is much easier to filter out than an
unsolicited (possibly valid, possibly invalid) Share Creation
Notification Request, since the Invite Acceptance Request needs to
contain an Invite Token that was previously uniquely generated at the
Invite Sender OCM server.</t>

</section>
</section>
</section>
<section anchor="ocm-api-discovery"><name>OCM API Discovery</name>

<section anchor="introduction-1"><name>Introduction</name>

<t>After establishing contact as discussed in the previous section, the
Sharing User MAY send the Share Creation Gesture to the Sending Server.
The Sharing User MUST provide the following information:</t>

<t><list style="symbols">
  <t>Resource to be shared</t>
  <t>Protocol to be offered for access</t>
  <t>Sending Party's identifier</t>
  <t>Receiving Party's identifier</t>
  <t>Receiving Server FQDN</t>
  <t>OPTIONAL: Share Requirements</t>
  <t>OPTIONAL: Share Name</t>
  <t>OPTIONAL: Share Permissions</t>
</list></t>

<t>The next step is for the Sending Server to additionally discover:</t>

<t><list style="symbols">
  <t>if the Receiving Server is trusted</t>
  <t>if the Receiving Server supports OCM</t>
  <t>if so, which version and with which optional functionality</t>
  <t>at which URL</t>
  <t>the public key the Receiving Server will use for HTTP Signatures (if
any)</t>
</list></t>

<t>The Sending Server MAY first perform denylist and allowlist checks on
the FQDN.</t>

<t>If a finite allowlist of Receiving Servers exists on the Sending Server
side, then this list MAY already contain all necessary information.</t>

<t>If the FQDN passes the denylist and/or allowlist checks, but no details
about its OCM API are known, the Sending Server can use the following
process to try to fetch this information from the Receiving Server.</t>

<t>This process MAY be influenced by a VPN connection and/or IP
allowlisting.</t>

<t>When OCM API Discovery can occur in preparation of a Share Creation
Notification, the Sending Server takes on the 'Discovering Server' role
and the Receiving Server plays the role of 'Discoverable Server'.</t>

</section>
<section anchor="process"><name>Process</name>

<t>At the start of the process, the Discovering Server has either an OCM
Address, or just an FQDN from for instance the <spanx style="verb">recipientProvider</spanx>
field of an Invite Acceptance Request.</t>

<t>Step 1: In case it has an OCM Address, it SHOULD first extract <spanx style="verb">&lt;fqdn&gt;</spanx>
from it (the part after the last <spanx style="verb">@</spanx> sign).
Step 2: The Discovering Server SHOULD attempt OCM API Discovery via a
HTTP GET request to <spanx style="verb">https://&lt;fqdn&gt;/.well-known/ocm</spanx>.
Step 3: If that results in a valid HTTP response with a valid JSON
response body within reasonable time, go to step 7.
Step 4: If not, try a HTTP GET with <spanx style="verb">https://&lt;fqdn&gt;/ocm-provider</spanx> as
the URL instead.
Step 5: If that results in a valid HTTP response with a valid JSON
response body within reasonable time, go to step 7.
Step 6: If not, fail. Implementations MAY fallback to HTTP instead
of HTTPS in testing setups and retry steps 2-5, in particular when
an optional port is given in the address.
Step 7: The JSON response body is the data that was discovered.</t>

</section>
<section anchor="fields"><name>Fields</name>

<t>The JSON response body offered by the Discoverable Server SHOULD
contain the following information about its OCM API:</t>

<t><list style="symbols">
  <t>REQUIRED: enabled (boolean) - Whether the OCM service is enabled at
this endpoint</t>
  <t>REQUIRED: apiVersion (string) - The OCM API version this endpoint
supports.  Example: <spanx style="verb">"1.2.1"</spanx></t>
  <t>REQUIRED: endPoint (string) - The URI of the OCM API available at
this endpoint.  Example: <spanx style="verb">"https://my-cloud-storage.org/ocm"</spanx></t>
  <t>OPTIONAL: provider (string) - A friendly branding name of this
endpoint.  Example: <spanx style="verb">"MyCloudStorage"</spanx></t>
  <t>REQUIRED: resourceTypes (array) - A list of all resource types this
server supports in both the Sending Server role and the Receiving
Server role, with their access protocols.  Each item in this list
MUST itself be an object containing the following fields:
  <list style="symbols">
      <t>name (string) - A supported resource type (file, calendar,
contact, ...).
Implementations MUST offer support for at least one
resource type, where <spanx style="verb">file</spanx> is the commonly supported
one.  Each resource type is identified by its <spanx style="verb">name</spanx>:
the list MUST NOT contain more than one resource type
object per given <spanx style="verb">name</spanx>.</t>
      <t>shareTypes (array of string) -
The supported recipient share types.  MUST contain
<spanx style="verb">"user"</spanx> at a minimum, plus optionally <spanx style="verb">"group"</spanx> and
<spanx style="verb">"federation"</spanx>.
Example: <spanx style="verb">["user"]</spanx></t>
      <t>protocols (object) - The supported protocols for accessing Shared
Resources of this type.
Implementations that offer <spanx style="verb">file</spanx> Resources MUST
support at least <spanx style="verb">webdav</spanx>,
any other combination of Resources and protocols is
optional.  Example:
<spanx style="verb">json
        {
          "webdav": "/remote/dav/ocm/",
          "webapp": "/app/ocm/",
          "talk": "/apps/spreed/api/"
        }
        </spanx>
Fields:
      <list style="symbols">
          <t>webdav (string) - The top-level WebDAV [RFC4918] path at this
endpoint.  In order to access a Remote Resource, implementations
MAY use this path as a prefix, or as the full path (see sharing
examples).</t>
          <t>webapp (string) - The top-level path for web apps at this
endpoint.  This value is provided for documentation
purposes, and it SHOULD NOT be intended as a prefix
for share requests.</t>
          <t>datatx (string) - The top-level path used for data transfers.
This value is provided for documentation purposes,
and it SHOULD NOT be intended as a prefix.  In
addition, implementations are expected to execute
the transfer using WebDAV [RFC4918] as the wire protocol.</t>
          <t>Any additional protocol supported for this Resource type MAY be
advertised here, where the value MAY correspond to
a top-level URI to be used for that protocol.</t>
        </list></t>
    </list></t>
  <t>OPTIONAL: capabilities (array of string) - The optional capabilities
supported by this OCM Server.
As implementations MUST accept Share Creation Notifications
to be compliant, it is not necessary to expose that as a
capability.
Example: <spanx style="verb">["receive-code", "webdav-uri"]</spanx>.  The array MAY
include for instance:
_ <spanx style="verb">"enforce-mfa"</spanx> - to indicate that this OCM Server can apply a
Sending Server's MFA requirements for a Share on their behalf.
_ <spanx style="verb">"webdav-uri"</spanx> - to indicate that this OCM Server can append a
relative URI to the path listed for WebDAV [RFC4918] in the
appropriate <spanx style="verb">resourceTypes</spanx> entry <spanx style="verb">"protocol-object"</spanx> - to
indicate that this OCM Server can receive a Share Creation
Notification whose <spanx style="verb">protocol</spanx> object contains one property per
supported protocol instead of containing the standard <spanx style="verb">name</spanx> and
<spanx style="verb">options</spanx> properties.
_ <spanx style="verb">"invites"</spanx> - to indicate the server would support acting as an
Invite Sender or Invite Receiver OCM Server.  This might be useful
for suggesting to a user that existing contacts might be upgraded
to the more secure (and possibly required) invite flow.
_ <spanx style="verb">"receive-code"</spanx> - to indicate that this OCM Server can receive a
<spanx style="verb">code</spanx> as part of a Share Creation Notification, and exchange it
for a bearer token at the Sending Server's <spanx style="verb">/token</spanx> API endpoint.
_ <spanx style="verb">"invite-wayf"</spanx> - to indicate that this OCM Server exposes a WAYF
Page to facilitate the Invite flow.</t>
  <t>OPTIONAL: criteria (array of string) - The criteria for accepting a
Share Creation Notification.
As all Receiving Servers SHOULD require the use of TLS in API
calls, it is not necessary to expose that as a criterium.
Example: <spanx style="verb">["http-request-signatures", "code"]</spanx>.  The array MAY
include for instance:
_ <spanx style="verb">"http-request-signatures"</spanx> - to indicate that API requests
without http signatures will be rejected.
_ <spanx style="verb">"code"</spanx> - to indicate that API requests without code will be
rejected (i.e.  the <spanx style="verb">sharedSecret</spanx> in the protocol details will be
ignored).
_ <spanx style="verb">"denylist"</spanx> - some servers MAY be blocked based on their IP
address
_ <spanx style="verb">"allowlist"</spanx> - unknown servers MAY be blocked based on their IP
address * <spanx style="verb">"invite"</spanx> - an invite MUST have been exchanged between the
sender and the receiver before a Share Creation Notification can be
sent</t>
  <t>OPTIONAL: publicKey (object) - The signatory used to sign outgoing
request to confirm its origin.
 The signatory is optional, but if present, it MUST contain
two string fields, <spanx style="verb">id</spanx> and <spanx style="verb">publicKeyPem</spanx>.
properties:
  <list style="symbols">
      <t>REQUIRED keyId (string) unique id of the key in URI format.  The
hostname set the origin of the request and MUST be
identical to the current discovery endpoint.
Example: https://my-cloud-storage.org/ocm#signature</t>
      <t>REQUIRED publicKeyPem (string) - PEM-encoded version of the public
key.
Example:
"----BEGIN PUBLIC KEY----\n...\n----END PUBLIC KEY----\n"</t>
    </list></t>
  <t>OPTIONAL: inviteAcceptDialog (string) - URL path of a web page where
a user can accept an invite, when query parameters <spanx style="verb">"token"</spanx> and
<spanx style="verb">"providerDomain"</spanx> are provided.  Implementations that offer the
<spanx style="verb">"invites"</spanx> capability SHOULD provide this URL as well in order to
enhance the UX of the Invite Flow.  If for example
<spanx style="verb">"/index.php/apps/sciencemesh/accept"</spanx> is specified here then a WAYF
Page SHOULD redirect the end-user to
<spanx style="verb">/index.php/apps/sciencemesh/accept?token=zi5kooKu3ivohr9a&amp;providerDomain=example.com</spanx>.</t>
</list></t>

</section>
</section>
<section anchor="share-creation-notification"><name>Share Creation Notification</name>

<t>To create a Share, the Sending Server SHOULD make a HTTP POST request</t>

<t><list style="symbols">
  <t>to the <spanx style="verb">/shares</spanx> path in the Receiving Server's OCM API</t>
  <t>using <spanx style="verb">application/json</spanx> as the <spanx style="verb">Content-Type</spanx> HTTP request header</t>
  <t>its request body containing a JSON document representing an object
with the fields as described below</t>
  <t>using TLS</t>
  <t>using httpsig [RFC9421]</t>
</list></t>

<section anchor="fields-1"><name>Fields</name>

<t><list style="symbols">
  <t>REQUIRED shareWith (string)
OCM Address of the user, group or federation the provider
wants to share the Resource with.  This MUST be known
in advance, either via a previous Invitation or through
other means.
Example: "51dc30ddc473d43a6011e9ebba6ca770@geant.org"</t>
  <t>REQUIRED name (string)
Name of the Resource (file or folder).
Example: "resource.txt"</t>
  <t>OPTIONAL description (string)
Optional description of the Resource (file or folder).
Example: "This is the Open API Specification file (in YAML
format) of the Open Cloud Mesh API."</t>
  <t>REQUIRED providerId (string)
Opaque value to identify the Shared Resource at the provider side.
This MUST be unique per Resource and per share, such that multiple
shares of a given Resource are guaranteed to get different values.
Example: 7c084226-d9a1-11e6-bf26-cec0c932ce01</t>
  <t>REQUIRED owner (string) -
OCM Address of the user who owns the
Resource.
Example: "6358b71804dfa8ab069cf05ed1b0ed2a@apiwise.nl"</t>
  <t>REQUIRED sender (string) -
OCM Address of the user that wants to share
the Resource.
Example: "527bd5b5d689e2c32ae974c6229ff785@apiwise.nl"</t>
  <t>OPTIONAL ownerDisplayName (string)
Display name of the owner of the Resource
Example: "Dimitri"</t>
  <t>OPTIONAL senderDisplayName (string)
Display name of the user that wants to share the Resource
Example: "John Doe"</t>
  <t>REQUIRED shareType (string)
SHOULD have a value of "user", "group", or "federation", to
indicate that the first part of the <spanx style="verb">shareWith</spanx> OCM Address refers
to a Receiving Party who is a single user of the Receiving Server,
a group of users at the Receiving Server, or a group of users that
spans multiple OCM Servers belonging to a federation as exposed by
a Directory Service, including at least one user at the Receiving
Server.
In the federation case, OCM Servers MAY resolve the actual
recipients by either querying external AAI systems, or exchanging
the groups' metadata between themselves.  Such exchange is out of
scope for this version of the this specification.
Alternatively, the Receiving Server MAY hold the federated groups'
metadata and act as an OCM proxy, forwarding the OCM requests to
the actual members of the federation.</t>
  <t>REQUIRED resourceType (string)
Resource type (file, calendar, contact, ...)</t>
  <t>OPTIONAL expiration (integer)
The expiration time for the OCM share, in seconds
of UTC time since Unix epoch.  If omitted, it is assumed
that the share does not expire.</t>
  <t>OPTIONAL code (string)
A nonce to be exchanged for a (potentially short-lived)
bearer token at the Sending Server's /token endpoint.</t>
  <t>REQUIRED protocol (object)
JSON object with specific options for each protocol.
The supported protocols are: - <spanx style="verb">webdav</spanx>, to access the data -
<spanx style="verb">webapp</spanx>, to access remote web applications - <spanx style="verb">datatx</spanx>, to transfer
the data to the remote endpoint.  <vspace blankLines='1'/>
    <figure><artwork><![CDATA[
    Other custom protocols might be added in the future.

    In case a single protocol is offered, there are three ways to
    specify this object:
    Option 1: Set the `name` field to the name of the protocol,
    and put the protocol details in a field named `options`.
    Option 2: Set the `name` field to the name of the protocol,
    and put the protocol details in a field carrying the name of
    the protocol.
    Option 3: Set the `name` field to `multi`, and put the
    protocol details in a field carrying the name of the protocol.

          Option 1 using the `options` field is now deprecated.
          Implementations are encouraged to transition to the new
          optional properties defined below, such that this field
          may be removed in a future major version of the spec.

    When specifying more than one protocol as different ways to
    access the Share, the `name` field needs to be set to `multi`.
]]></artwork></figure>
  </t>
</list></t>

<t>If <spanx style="verb">multi</spanx> is given, one or more protocol
endpoints are expected to be defined according to the
optional properties specified below.
Otherwise, at least <spanx style="verb">webdav</spanx> is expected to be
supported, and its options MAY be given in the opaque
<spanx style="verb">options</spanx> payload for compatibility with v1.0
implementations (see examples).  Note though that this
format is deprecated.
Warning: client implementers should be aware that v1.1
servers MAY support both <spanx style="verb">webdav</spanx> and <spanx style="verb">multi</spanx>, but v1.0
servers MAY only support <spanx style="verb">webdav</spanx>.</t>

<t><list style="symbols">
  <t>Protocol details for <spanx style="verb">webdav</spanx> MAY contain:
  <list style="symbols">
      <t>REQUIRED uri (string)
A URI to access the Remote Resource.  The URI
SHOULD be relative, in which case the prefix
exposed by the <spanx style="verb">/.well-known/ocm</spanx> endpoint MUST
be used.  Absolute URIs are deprecated.</t>
      <t>OPTIONAL sharedSecret (string) - REQUIRED if no <spanx style="verb">code</spanx> field is
given for the Share as a whole (see above).  An
optional secret to be used to access the Resource,
such as a bearer token.
To prevent leaking it in logs it MUST NOT appear in
any URI.</t>
      <t>OPTIONAL permissions (array of strings) -
The permissions granted to the sharee.  A subset
of: - <spanx style="verb">read</spanx> allows read-only access including
download of a copy.  - <spanx style="verb">write</spanx> allows create, update, and delete
rights on the Resource.  - <spanx style="verb">share</spanx> allows re-share rights on the
Resource.</t>
      <t>OPTIONAL requirements (array of strings) -
The requirements that the sharee MUST fulfill to
access the Resource.  A subset of: - <spanx style="verb">mfa-enforced</spanx> requires the
consumer to be MFA-authenticated.  This MAY be used if the
recipient provider exposes the <spanx style="verb">enforce-mfa</spanx>
capability.  - <spanx style="verb">use-code</spanx> requires the consumer to exchange
the given <spanx style="verb">code</spanx> via a signed HTTPS request.  This
MAY be used if the recipient provider exposes the
<spanx style="verb">receive-code</spanx> capability.</t>
    </list></t>
  <t>Protocol details for <spanx style="verb">webapp</spanx> MAY contain:
  <list style="symbols">
      <t>REQUIRED uri (string)
A URI to a client-browsable view of the Shared
Resource, such that users MAY use the web
applications available at the site.  The URI SHOULD
be relative, in which case the prefix exposed by
the <spanx style="verb">/.well-known/ocm</spanx> endpoint MUST be used.
Absolute URIs are deprecated.</t>
      <t>REQUIRED viewMode (string)
The permissions granted to the sharee.  A subset of: - <spanx style="verb">view</spanx>
allows access to the web app in view-only mode.  - <spanx style="verb">read</spanx> allows
read and download access via the web app.  - <spanx style="verb">write</spanx> allows full
editing rights via the web app.</t>
      <t>OPTIONAL sharedSecret (string)
An optional secret to be used to access the remote
web app, for example in the form of a bearer token.</t>
    </list></t>
  <t>Protocol details for <spanx style="verb">datatx</spanx> MAY contain:
  <list style="symbols">
      <t>REQUIRED srcUri (string)
A URI to access the Remote Resource.  The URI
SHOULD be relative, in which case the prefix
exposed by the <spanx style="verb">/.well-known/ocm</spanx> endpoint MUST be
used.  Absolute URIs are deprecated.</t>
      <t>OPTIONAL sharedSecret (string)
An optional secret to be used to access the
Resource, for example in the form of a bearer
token.  To prevent leaking it in logs it MUST NOT
appear in any URI.</t>
      <t>OPTIONAL size (integer)
The size of the file to be transferred from the
sending server.</t>
    </list></t>
</list></t>

</section>
<section anchor="decision-to-discard"><name>Decision to Discard</name>

<t>The Receiving Server MAY discard the notification if any of the
following hold true:</t>

<t><list style="symbols">
  <t>the HTTP Signature is missing but the Sending Server does expose a
keypair discoverable from the FQDN part of the <spanx style="verb">sender</spanx> field in the
request body</t>
  <t>the HTTP Signature is missing</t>
  <t>the HTTP Signature is not valid</t>
  <t>no keypair is trusted or discoverable from the FQDN part of the
<spanx style="verb">sender</spanx> field in the request body</t>
  <t>the keypair used to generate the HTTP Signature doesn't match the one
trusted or discoverable from the FQDN part of the <spanx style="verb">sender</spanx> field
in the request body</t>
  <t>the Sending Server is denylisted</t>
  <t>the Sending Server is not allowlisted</t>
  <t>the Sending Party is not trusted by the Receiving Party (e.g., no
Invite was exchanged and/or the Sending Party's OCM Address does not
appear in the Receiving Party's address book)</t>
  <t>the Receiving Server is unable to act as an API client for (any of)
the protocol(s) listed for accessing the Resource</t>
  <t>an initial check shows that the Resource cannot successfully be
accessed through (any of) the protocol(s) listed</t>
</list></t>

</section>
</section>
<section anchor="receiving-party-notification"><name>Receiving Party Notification</name>

<t>If the Share Creation Notification is not discarded by the Receiving
Server, they MAY notify the Receiving Party passively by adding the
Share to some inbox list, and MAY also notify them actively through for
instance a push notification or an email message.</t>

<t>They could give the Receiving Party the option to accept or reject the
share, or add the share automatically and only send an informational
notification that this happened.</t>

</section>
<section anchor="share-acceptance-notification"><name>Share Acceptance Notification</name>

<t>In response to a Share Creation Notification, the Receiving Server MAY
discover the OCM API of the Sending Server, starting from the <spanx style="verb">&lt;fqdn&gt;</spanx>
part of the <spanx style="verb">sender</spanx> field in the Share Creation Notification.</t>

<t>If the OCM API of the Sending Server is successfully discovered, the
Receiving Server MAY make a HTTP POST request</t>

<t><list style="symbols">
  <t>to the <spanx style="verb">/notifications</spanx> path in the Sending Server's OCM API</t>
  <t>using <spanx style="verb">application/json</spanx> as the <spanx style="verb">Content-Type</spanx> HTTP request header</t>
  <t>its request body containing a JSON document representing an object
with the fields as described below</t>
  <t>using TLS</t>
  <t>using httpsig [RFC9421]</t>
</list></t>

<section anchor="fields-2"><name>Fields</name>

<t><list style="symbols">
  <t>REQUIRED notificationType (string) - in a Share Acceptance
Notification it MUST be one of:
  <list style="symbols">
      <t>'SHARE_ACCEPTED'</t>
      <t>'SHARE_DECLINED'</t>
    </list></t>
  <t>REQUIRED providerId (string) - copied from the Share Creation
Notification for the Share this notification is about</t>
  <t>OPTIONAL resourceType (string) - copied from the Share Creation
Notification for the Share this notification is about</t>
  <t>OPTIONAL notification (object) - optional additional parameters,
depending on the notification and the resource type</t>
</list></t>

<t>For example, a notification MAY be sent by a recipient to let the
provider know that the recipient declined a share.  In this case, the
provider site MAY mark the share as declined for its user(s).
Similarly, it MAY be sent by a provider to let the recipient know that
the provider removed a given share, such that the recipient MAY clean
it up from its database.  A notification MAY also be sent to let a
recipient know that the provider removed that recipient from the list
of trusted users, along with any related share.  The recipient MAY
reciprocally remove that provider from the list of trusted users, along
with any related share.</t>

<t>Notifications from Sending Server to Receiving Server SHOULD use
httpsig [RFC9421] so the Receiving Server can authenticate the origin
of the notification.  Receiving Servers SHOULD decline notifications
from Sending Servers without httpsig as it can't identify where the 
notification is coming from.</t>

<section anchor="receiving-party-notification-1"><name>Receiving Party Notification</name>

<t>If the Share Creation Notification is not discarded by the Receiving
Server, they MAY notify the Receiving Party passively by adding the
Share to some inbox list, and MAY also notify them actively through for
instance a push notification or an email message.</t>

<t>They could give the Receiving Party the option to accept or reject the
Share, or add the Share automatically and only send an informational
notification that this happened.</t>

</section>
</section>
</section>
<section anchor="resource-access"><name>Resource Access</name>

<t>To access the Resource, the Receiving Server MAY use multiple ways,
depending on the body of the Share Creation Notification.  The procedure
is as follows:</t>

<t><list style="numbers" type="1">
  <t>The receiver MUST extract the OCM Server FQDN from the <spanx style="verb">sender</spanx>
field of the received share, and MUST query the
<xref target="ocm-api-discovery">Discovery</xref> endpoint at that address: the
<spanx style="verb">resourceTypes[0].protocols.webdav</spanx> value is the
<spanx style="verb">&lt;sender-ocm-path&gt;</spanx> to be used in step 3.</t>
  <t>If <spanx style="verb">code</spanx> is not empty, the receiver SHOULD make a signed POST
request to the <spanx style="verb">/token</spanx> path inside the Sending Server's OCM API, to
exchange the code for a short-lived bearer token, and then use that
bearer token to access the Resource.</t>
  <t>If <spanx style="verb">protocol.name</spanx> = <spanx style="verb">webdav</spanx>, the receiver SHOULD inspect the
<spanx style="verb">protocol.options</spanx> property.  If it contains a <spanx style="verb">sharedSecret</spanx>, as in
the <eref target="https://cs3org.github.io/OCM-API/docs.html?branch=develop&amp;repo=OCM-API&amp;user=cs3org#/paths/~1shares/post">legacy example</eref>,
then the receiver SHOULD make a HTTP PROPFIND request to
<spanx style="verb">https://&lt;sharedSecret&gt;:@&lt;sender-host&gt;&lt;sender-ocm-path&gt;</spanx>.  Note that
this access method, based on Basic Auth, is <em>deprecated</em> and may be
removed in a future release of the Protocol.</t>
  <t>Otherwise, if <spanx style="verb">protocol.name</spanx> = <spanx style="verb">multi</spanx>, the receiver MUST inspect
the <spanx style="verb">protocol.webdav.uri</spanx> property: if it's a complete URI, the
receiver MUST make a HTTP PROPFIND request against it to access the
Remote Resource.  If it only contains an identifier <spanx style="verb">&lt;key&gt;</spanx>, the
receiver MUST make a HTTP PROPFIND request to
<spanx style="verb">https://&lt;sender-host&gt;&lt;sender-ocm-path&gt;/&lt;key&gt;</spanx> in order to access
the Remote Resource.  Additionally, the receiver MUST pass an
<spanx style="verb">Authorization: bearer</spanx> header with either the short-lived bearer
token obtained in step 2, if applicable, or the
<spanx style="verb">protocol.webdav.sharedSecret</spanx> value.</t>
</list></t>

<t>In all cases, in case the Shared Resource is a folder and the Receiving
Server accesses a Resource within that shared folder, it SHOULD append
its relative path to that URL.  In other words, the Sending Server
SHOULD support requests to URLs such as
<spanx style="verb">https://&lt;sender-host&gt;&lt;sender-ocm-path&gt;/path/to/resource.txt</spanx>.</t>

<t>Additionally, if <spanx style="verb">protocol.&lt;protocolname&gt;.requirements</spanx> includes
<spanx style="verb">mfa-enforced</spanx>, the Receiving Server MUST ensure that the Receiving
Party has been authenticated with MFA, or prompt the consumer in order
to elevate their session, if applicable.</t>

</section>
<section anchor="share-deletion"><name>Share Deletion</name>

<t>A <spanx style="verb">"SHARE_ACCEPTED"</spanx> notification followed by a <spanx style="verb">"SHARE_UNSHARED"</spanx>
notification is equivalent to a <spanx style="verb">"SHARE_DECLINED"</spanx> notification.</t>

<t>Note that the Sending Server MAY at any time revoke access to a
Resource (effectively undoing or deleting the Share) without notifying
the Receiving Server.</t>

</section>
<section anchor="share-updating"><name>Share Updating</name>

<t>Some implementations have experimented with a
<spanx style="verb">"RESHARE_CHANGE_PERMISSION"</spanx>notification, but the payload and side
effects such a notification may have are out of scope of this version
of this specification.
The Receiving Party sending such a notification has no way of knowing
if the Sending Party understood and processed the reshare request
or not.</t>

</section>
<section anchor="resharing"><name>Resharing</name>

<t>The <spanx style="verb">"REQUEST_RESHARE"</spanx> and <spanx style="verb">"RESHARE_UNDO"</spanx> notification types MAY be
used by the Receiving Server to persuade the Sending Server to share the
same Resource with another Receiving Party.
The details of the payload and side effects such a notification may
have are out of scope of this version of this specification.
Note that the Receiving Party sending such a notification has no way of
knowing if the Sending Party understood and processed the reshare
request or not.  In all cases, the Receiving Server MUST NOT reshare
a Resource without an explicit grant from the Sending Server.</t>

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

<section anchor="well-known-uri-for-the-discovery"><name>Well-Known URI for the Discovery</name>

<t>The following value is to be registered in the "Well-Known URIs"
registry (using the template from [RFC5785]):
   URI suffix: ocm
   Change controller: IETF
   Specification document(s): the present Draft, once in RFC form
   Related information: N/A</t>

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

<section anchor="trust"><name>Trust</name>

<t>There are several areas that are not covered by this specification.
Most importantly we do not provide a way of establishing trust between
servers, even though some features of the protocol rely on trust, such
as the <spanx style="verb">mfa-enforced</spanx> requirement.</t>

<t>Trust needs to be established out of band, but there are some features
of the protocol that <em>can</em> be used to assist operators in establishing
trust.  For instance, invite flow can be used to establish that users
know and have out of band connections with other users on an OCM server.</t>

<t>Further more the Directory Service feature can be used to establish a
trusted federation, where a central authority can be trusted to
implement measures for auditing and adding only trusted servers into the
discovery service.</t>

<section anchor="httpsig"><name>httpsig</name>

<t>It is RECOMMENDED to use signed messages, "httpsig" [RFC9421], to
verify that an OCM server is the server you expect it to be, and SHOULD
be done unless you have a niche use case.</t>

</section>
</section>
<section anchor="legacy-shared-secrets"><name>Legacy shared secrets</name>

<t>The legacy format of an OCM Share Notification with shared secrets is
only provided for backwards compatibility with existing implementations.
Implementers SHOULD NOT use it and prefer short-lived tokens instead.</t>

</section>
</section>
<section anchor="references"><name>References</name>

<section anchor="normative-references"><name>Normative References</name>

<t>[RFC2119] Bradner, S. "<eref target="https://datatracker.ietf.org/doc/html/rfc2119">Key words for use in RFCs to Indicate
Requirement Levels</eref>",
March 1997.</t>

<t>[RFC4918] Dusseault, L. M. "<eref target="https://datatracker.ietf.org/html/rfc4918/">HTTP Extensions for Web Distributed
Authoring and Versioning</eref>",
June 2007.</t>

<t>[RFC8174] Leiba, B. "<eref target="https://datatracker.ietf.org/html/rfc8174">Ambiguity of Uppercase vs Lowercase in RFC 2119
Key Words</eref>", May 2017.</t>

<t>[RFC9421] Backman, A., Richer, J. and Sporny, M. "<eref target="https://tools.ietf.org/html/rfc9421">HTTP Message
Signatures</eref>", February 2024.</t>

<t>[RFC3986] Berners-Lee, T., Fielding, R. and Masinter, L. 
"<eref target="https://datatracker.ietf.org/doc/html/rfc3986">Uniform Resource Identifier (URI): Generic Syntax
</eref>", January 2005</t>

<t>[RFC8615] Nottingham, M. "<eref target="https://datatracker.ietf.org/doc/html/rfc8615">Well-Known Uniform Resource Identifiers 
(URIs)</eref>", May 2019</t>

</section>
<section anchor="informative-references"><name>Informative References</name>

<t>[RFC6749] Hardt, D. (ed), "<eref target="https://datatracker.ietf.org/html/rfc6749">The OAuth 2.0 Authorization Framework</eref>", October 2012.</t>

</section>
</section>
<section anchor="appendix-a-multi-factor-authentication"><name>Appendix A: Multi-factor Authentication</name>

<t>If a Receiving Server exposes the capability <spanx style="verb">enforce-mfa</spanx>, it
indicates that it will try and comply with a MFA requirement set on a
Share.  If the Sending Server trusts the Receiving Server, the Sending
Server MAY set the requirement <spanx style="verb">mfa-enforced</spanx> on a Share, which the
Receiving Server MUST honor.  A compliant Receiving Server that signals
that it is MFA-capable MUST NOT allow access to a Resource protected
with the <spanx style="verb">mfa-enforced</spanx> requirement, if the Receiving Party has not
provided a second factor to establish their identity with greater
confidence.</t>

<t>Since there is no way to guarantee that the Receiving Server will
actually enforce the MFA requirement, it is up to the Sending Server to
establish a trust with the Receiving Server such that it is reasonable
to assume that the Receiving Server will honor the MFA requirement.
This establishment of trust will inevitably be implementation
dependent, and can be done for example using a pre approved allow list
of trusted Receiving Servers.  The procedure of establishing trust is
out of scope for this specification: a mechanism similar to the
<eref target="https://sciencemesh.io">ScienceMesh</eref> integration for the
<xref target="invite-flow">Invite</xref> capability may be envisaged.</t>

</section>
<section anchor="appendix-b-request-signing"><name>Appendix B: Request Signing</name>

<t>A request is signed by adding the signature in the headers.  The sender
also needs to expose the public key used to generate the signature.  The
receiver can then validate the signature and therefore the origin of
the request.
To help debugging, it is RECOMMENDED to also add all properties used in
the signature as headers, even if they can easily be re-generated from
the payload.</t>

<t>Note: Signed requests prove the identity of the sender but do not
encrypt nor affect its payload.</t>

<t>Here is an example of headers needed to sign a request.</t>

<t><spanx style="verb">
  {
    "@request-target": "post /path",
    "content-length": 380,
    "date": "Mon, 08 Jul 2024 14:16:20 GMT",
    "content-digest": "SHA-256=U7gNVUQiixe5BRbp4...",
    "host": "hostname.of.the.recipient",
    "Signature": "keyId=\"https://author.hostname/key\",algorithm=
      \"rsa-sha256\",headers=\"content-length date digest host\",
      signature=\"DzN12OCS1rsA[...]o0VmxjQooRo6HHabg==\""
  }
</spanx></t>

<t><list style="symbols">
  <t>'@request-target' (optional) contains the reached endpoint and
the used method,</t>
  <t>'content-length' is the total length of the payload of the
request,</t>
  <t>'date' is the date and time when the request has been
sent,</t>
  <t>'content-digest' is a checksum of the payload of the
request,</t>
  <t>'host' is the hostname of the recipient of the request (remote when
signing outgoing request, local on incoming request),</t>
  <t>'Signature' contains the signature generated using the private key
and details on its generation:
  <list style="symbols">
      <t>'keyId' is a unique id, formatted as an url; hostname is used to
retrieve the public key via custom discovery</t>
      <t>'algorithm' specify the algorithm used to generate signature</t>
      <t>'headers' specify the properties used when generating the
signature</t>
      <t>'signature' the signature of an array containing the properties
listed in 'headers'.  Some properties like content-length, date,
content-digest, and host are mandatory to protect against
authenticity override.</t>
    </list></t>
</list></t>

<section anchor="how-to-generate-the-signature-for-outgoing-request"><name>How to generate the Signature for outgoing request</name>

<t>After properties are set in the headers, the Signature is generated and
added to the list.</t>

<t>This is a pseudo-code example for generating the <spanx style="verb">Signature</spanx> header for
outgoing requests:</t>

<t>```
headers = {
  'content-length': length_of(payload),
  # Use a function to get the current GMT date as 'D, d M Y H:i:s T'
  'date': current_gmt_datetime(),
  'content-digest': 'SHA-256=' + base64_encode(hash('sha256',
        utf8_encode(payload))),
  'host': 'recipient-fqdn',
}</t>

<t>signed = ssl_sign(concatenate_with_newlines(headers),
    private_key, 'sha256')
signature = {
    'keyId': 'sender.fqdn',  # The sending server's FQDN
    'algorithm': 'rsa-sha256',
    'headers': 'content-length date content-digest host',
    'signature': signed,
}</t>

<t>headers['Signature'] = format_signature(signature)
```</t>

</section>
<section anchor="how-to-confirm-signature-on-incoming-request"><name>How to confirm Signature on incoming request</name>

<t>The first step would be to confirm the validity of each
properties:</t>

<t><list style="symbols">
  <t><spanx style="verb">content-length</spanx> and <spanx style="verb">content-digest</spanx> can be regenerated and compared
from the payload of the request,</t>
  <t>a maximum TTL MUST be applied to <spanx style="verb">date</spanx> and current
timestamp,</t>
  <t>regarding data contained in the <spanx style="verb">Signature</spanx>
header:
  <list style="symbols">
      <t>using <spanx style="verb">keyId</spanx> to get the public key from remote
signatory,</t>
      <t><spanx style="verb">headers</spanx> is used to generate the clear version of the
signature and MUST contain at least <spanx style="verb">content-length</spanx>, <spanx style="verb">date</spanx>,
<spanx style="verb">content-digest</spanx> and <spanx style="verb">host</spanx>,</t>
      <t><spanx style="verb">signature</spanx> is the encrypted version of the
signature.</t>
    </list></t>
</list></t>

<t>Here is an example of how to verify the signature using the headers,
the signature and the public key:</t>

<t>```
clear = {
    'content-length': length_of(payload),
    'date': 'Mon, 08 Jul 2024 14:16:20 GMT',
    'content-digest': 'SHA-256=' + base64_encode(hash('sha256',
          utf8_encode(payload))),  # Recompute digest for verification
    'host': 'sender-fqdn',
}</t>

<t>signed = headers['Signature']
verification_result = ssl_verify(concatenate_with_newlines(clear),
                                 signed, public_key, 'sha256')</t>

<t>if not verification_result then
    raise InvalidSignatureException
```</t>

</section>
<section anchor="validating-the-payload"><name>Validating the payload</name>

<t>Following the validation of the signature, the host SHOULD also confirm
the validity of the payload, that is ensuring that the actions implied
in the payload actually initiated on behalf of the source of the
request.</t>

<t>As an example, if the payload is about initiating a new share, the file
owner has to be an account from the instance at the origin of the
request.</t>

</section>
</section>
<section anchor="appendix-c-directory-service"><name>Appendix C: Directory Service</name>

<t>A third-party Directory Service is a back-end service used to federate
multiple OCM Servers and facilitate the Invite flow.  It is expected to
expose, via anonymous HTTP GET, a JSON document with the following
format:</t>

<t><list style="symbols">
  <t>REQUIRED: <spanx style="verb">federation</spanx> - a human-readable name for the list of OCM
Servers exposed by the Directory Service</t>
  <t>REQUIRED: <spanx style="verb">servers</spanx> - a JSON array of objects to describe the list
of OCM Servers with the following string fields:
  <list style="symbols">
      <t>REQUIRED: <spanx style="verb">url</spanx> - an absolute URL identifying the
OCM Server.  It MUST:
      <list style="symbols">
          <t>include scheme: either <spanx style="verb">https://</spanx> or
(for testing purposes) <spanx style="verb">http://</spanx></t>
          <t>include host (either a FQDN or an IP address)</t>
          <t>MAY include a non-default port</t>
          <t>MUST NOT include a base path (e.g., <spanx style="verb">/ocm</spanx>)</t>
          <t>MUST NOT include userinfo, query, or fragment</t>
        </list></t>
      <t>REQUIRED: <spanx style="verb">displayName</spanx> - a human-readable name
for the OCM Server
Example:</t>
    </list></t>
</list></t>

<t><spanx style="verb">json
{
  "federation": "The ScienceMesh Directory",
  "servers": [
    {
      "url": "https://ocm-server-1.example.org",
      "displayName": "OCM Server 1"
    },
    {
      "url": "https://ocm-server-2.example.org:4443",
      "displayName": "OCM Server 2"
    },
    {
      "url": "http://192.168.1.1:8080",
      "displayName": "OCM Server 3"
    }
  ]
}
</spanx></t>

</section>
<section anchor="acknowledgements"><name>Acknowledgements</name>

<t>Our deepest thanks and appreciation go to the people who started the
work on what would become this specification in 2015.  In particular we
want to thank (in alphabetical order) Guido Aben, Russell Albert,
Holger Angenent, David Antoš, Hrachya Astsatryan, Kurt Bauer,
Charles du Jeu, Andreas Eckey, David Gillard, Andranik Hayrapetyan Wahi,
Dimitri van Hees, Christoph Herzog, David Jericho, Frank Karlitschek,
Christian Kracher, Ralph Krimmel, Massimo Lamanna, Simon Leinen,
Jari Miettinen, Jakub Moscicki, Frederik Orellana, Vlad Roman,
Christian Schmitz, Woojin Seok, Rogier Spoor, Christian Sprajc,
Peter Szegedi, Ron Trompert, Benedikt Wegmann and Jonathan Xu.</t>

<t>We would also like to thank Ishank Arora, Gianmaria Del Monte,
Jörn Friedrich Dreyer, Richard Freitag, Hugo González Labrador,
Matthias Kraus, Maxence Lange, Lovisa Lugnegård, Sandro Mesterheide,
Antoon Prins and Björn Schießle for their direct contributions
to the specification.</t>

<t>Over the years many more people have been involved in the development
of OCM.  We would like to thank all of them for their contributions,
including Jean-Thomas Acquaviva, Samuel Alfageme Sainz,
Karsten Asshauer, Miroslav Bauer, Felix Böhm, Maciej Brzeźniak,
Diogo Castro, Gavin Charles Kennedy, Jarosław Czub, Milan Danecek,
Michael D'Silva, Lukasz Dutka, Pedro Ferreira, Renato Furter,
Klaas Freitag, Raman Ganguly, Eva Gergely, Hilary Goodson, Daniel Halbe,
Dave Heyns, Jan Holesovsky, Jan Hornicek, Carina Kemp, Fergus Kerins,
Andreas Klotz, Matthias Knoll, Christian Kracher, Mario Lassnig,
Claudius Laumanns, Anthony Leroy, Patrick Maier, Vladislav Makarenko,
Anna Manou, Rita Meneses, Zheng Meyer-Zhao, Crystal Michelle Chua,
Yoann Moulin, Daniel Müller, Frederik Müller, Rasmus Munk,
Michał Orzechowski, Jacek Pawel Kitowski, Iosif Peterfi,
Alessandro Petraro, Rene Ranger, Angelo Romasanta, David Rousse,
Carla Sauvanaud, Klaus Scheibenberger, Marcin Sieprawski,
Tilo Steiger, C.D. Tiwari, Alejandro Unger and Tom Wezepoel.</t>

</section>


  </middle>

  <back>








  </back>

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

-->

</rfc>

