<?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-05" 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="August" day="20"/>

    <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> - A string of the form
<spanx style="verb">&lt;Receiving Party's identifier&gt;@&lt;fqdn&gt;</spanx> which can be used to uniquely
identify a user or group "at" an OCM Server and MAY be referred to as
Federated Cloud ID.
<spanx style="verb">&lt;Receiving Party's identifier&gt;</spanx> is an opaque string, unique at the
server.  <spanx style="verb">&lt;fqdn&gt;</spanx> is the Fully Qualified Domain Name by which the
server is identified.  This MUST be the domain at which the
<spanx style="verb">/.well-known/ocm</spanx> endpoint of that server is hosted.</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.  After that, the Share MAY be
updated, deleted, and/or reshared.</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.
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
SHOULD 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)
Identifier to identify the Shared Resource at the provider
side.  This is unique per provider such that if the same
Resource is shared twice, this providerId will not be
repeated.
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 Servers, or
a group of users that is spread out over various servers,
including at least one user at the Receiving Server.</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.</t>

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

<t>This document has no IANA actions.</t>

</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>

</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,
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 Johnatan 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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
7na7XbJNkv8N4i3HRXjVAAA=

-->

</rfc>

