<?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.8) -->


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

]>


<rfc ipr="trust200902" docName="draft-lopresti-open-cloud-mesh-04" category="std" consensus="true">
  <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.com</email>
        <uri>https://pondersource.com</uri>
      </address>
    </author>
    <author initials="M." surname="Baghbani" fullname="Mahdi Baghbani">
      <organization>Ponder Source</organization>
      <address>
        <email>mahdi@pondersource.com</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="July" day="17"/>

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

    <abstract>


<?line 37?>

<t>Open Cloud Mesh 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>Open Cloud Mesh only handles the necessary interactions up to the point where the Receiving Party is informed that they were granted access to the Resource. The actual resource access is then left to protocols such as WebDAV and others.</t>



    </abstract>



  </front>

  <middle>


<?line 44?>

<section anchor="terms"><name>Terms</name>
<t>The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" in this document are to be interpreted as described in RFC 2119.</t>

<t>The key words "REQUIRED", "RECOMMENDED", "OPTIONAL" has the same meaning as "MUST", "SHOULD" and "MAY" respectively but are used instead of their counterparts where it makes more grammatical sense (such as marking fields in a JSON object).</t>

<t>We define the following concepts (with some non-normative references to related concepts from OAuth and elsewhere):</t>

<t><list style="symbols">
  <t><strong>Resource</strong> - the piece of data or interaction to which access is being granted, e.g. a file, folder, video call, or printer queue</t>
  <t><strong>Share</strong> - a policy rule stating that certain actors are allowed access to a Resource. Also: 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)</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)</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)</t>
      <t>takes the decision about authorizing attempts to access the Resource (the "Resource Server" role in OAuth)</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) 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>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>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>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. <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</t>
  <t><strong>Invite Receiver</strong> - the party receiving an Invite</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 needs to 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>
<t>### Rationale
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 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 Gesture 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 <eref target="https://datatracker.ietf.org/doc/rfc9421">httpsig</eref></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>
<t>## Introduction
After establishing contact as discussed in the previous section, the Sharing User can send the Share Creation Gesture to the Sending Server, providing the Sending Server with 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 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 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, folder, 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 path at this endpoint. In order to access
              a remote shared 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 to be 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 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:
  <list style="symbols">
      <t><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.</t>
      <t><spanx style="verb">"webdav-uri"</spanx> - to indicate that this OCM Server can append a relative URI to the path listed for WebDAV in the appropriate <spanx style="verb">resourceTypes</spanx> entry</t>
      <t><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.</t>
      <t><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.</t>
      <t><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.</t>
      <t><spanx style="verb">"invite-wayf"</spanx> - to indicate that this OCM Server exposes a WAYF Page to facilitate the Invite flow.</t>
    </list></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:
  <list style="symbols">
      <t><spanx style="verb">"http-request-signatures"</spanx> - to indicate that API requests without http signatures will be rejected.</t>
      <t><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).</t>
      <t><spanx style="verb">"denylist"</spanx> - some servers may be blocked based on their IP address</t>
      <t><spanx style="verb">"allowlist"</spanx> - unknown servers may be blocked based on their IP address</t>
      <t><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>
    </list></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-----\nMII...QDD\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 <eref target="https://datatracker.ietf.org/doc/rfc9421">httpsig</eref></t>
</list></t>

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

<t><list style="symbols">
  <t>REQUIRED shareWith (string)
        Consumer specific identifier of the user, group or federation the provider
        wants to share the resource with. This is known in advance.
        Please note that the consumer service endpoint is known in advance
        as well, so this is no part of the request body.
      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) -
        Provider specific identifier of the user who owns the resource.
      Example: "6358b71804dfa8ab069cf05ed1b0ed2a@apiwise.nl"</t>
  <t>REQUIRED sender (string) -
        Provider specific identifier of the user that wants to share the
        resource. Please note that the requesting provider is being
        identified on a higher level, so the former <spanx style="verb">remote</spanx> property
        is not part of the request body.
      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 indicated 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, folder, 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)
             An 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)
             An 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)
             An 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 <eref target="https://datatracker.ietf.org/doc/rfc9421">httpsig</eref></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>

<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:
1. 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.
2. 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.
3. 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.
4. 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>

<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 consmer 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="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>

<figure><artwork><![CDATA[
  {
    "(request-target)": "post /path",
    "content-length": 380,
    "date": "Mon, 08 Jul 2024 14:16:20 GMT",
    "digest": "SHA-256=U7gNVUQiixe5BRbp4Tg0xCZMTcSWXXUZI2\\/xtHM40S0=",
    "host": "hostname.of.the.recipient",
    "Signature": "keyId=\"https://author.hostname/key\",algorithm=\"rsa-sha256\",headers=\"content-length date digest host\",signature=\"DzN12OCS1rsA[...]o0VmxjQooRo6HHabg==\""
  }
]]></artwork></figure>

<t><list style="symbols">
  <t>'(request-target)' 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>'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, 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>

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

signed = ssl_sign(concatenate_with_newlines(headers), private_key, 'sha256')
signature = {
    'keyId': 'sender-fqdn',  # The sending server's FQDN; find its public key through OCM API discovery
    'algorithm': 'rsa-sha256',
    'headers': 'content-length date digest host',
    'signature': signed,
}

headers['Signature'] = format_signature(signature)
]]></artwork></figure>

</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">(request-target)</spanx> and <spanx style="verb">host</spanx> are immutable to the type of the request and the local/current host,</t>
  <t><spanx style="verb">content-length</spanx> and <spanx style="verb">digest</spanx> can be re-generated 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">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>

<figure><artwork><![CDATA[
clear = {
    '(request-target)': 'post /path',
    'content-length': length_of(payload),
    'date': 'Mon, 08 Jul 2024 14:16:20 GMT',  # The date used in the verification process
    'digest': 'SHA-256=' + base64_encode(hash('sha256', utf8_encode(payload))),  # Recompute the digest for verification
    'host': 'sender-fqdn',
}

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

if not verification_result then
    raise InvalidSignatureException
]]></artwork></figure>

</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:
  * REQUIRED: <spanx style="verb">federation</spanx> - a human-readable name for the list of OCM Servers exposed by the Directory Service
  * REQUIRED: <spanx style="verb">servers</spanx> - a JSON array of objects to describe the list of OCM Servers with the following string fields:
    * REQUIRED: <spanx style="verb">url</spanx> - the OCM Server's FQDN
    * REQUIRED: <spanx style="verb">displayName</spanx> - a human-readable name for the OCM Server
  Example:
  <spanx style="verb">json
  {
    "federation" : "The ScienceMesh Directory",
    "servers" : [
      {
       "url" : "https://ocm-server-1.fqdn",
       "displayName" : "OCM Server 1"
      },
      {
       "url" : "https://ocm-server-2.fqdn",
       "displayName" : "OCM Server 2"
      }
    ]
  }
 </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, Hugo González Labrador, Maxence Lange, Lovisa Lugnegård, Sandro Mesterheide, Antoon Prins and Björn Schissle 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, Christian Schmitz, Marcin Sieprawski, Tilo Steiger, C.D. Tiwari, Alejandro Unger and Tom Wezepoel.</t>

</section>


  </middle>

  <back>








  </back>

<!-- ##markdown-source:
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
2FVvNBqRFjz4/45ZeUZSyAAA

-->

</rfc>

