Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 18 additions & 15 deletions IETF-OCM-IP.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ at the Protocol Server.
on the access protocol) presents the access token to the Protocol
Server.
9. The Protocol Server verifies the token against the OCM Server's
published keys, looks up the Share Record by (issuer domain,
published keys, looks up the Share Record by (issuer server address,
`client_id`), cross-checks the identities bound into the token, and
serves the protocol-specific Resource access.

Expand Down Expand Up @@ -676,7 +676,7 @@ Revocation Request:
* with a request body containing a JSON document with the following
fields:

* REQUIRED `sender` (string) - an OCM Address whose domain part
* REQUIRED `sender` (string) - an OCM Address whose server part
identifies the paired OCM Server, subject to the same allowlist and
signature checks as all Integration API requests.
* REQUIRED `providerId` (string) - the `providerId` of the Share to
Expand Down Expand Up @@ -869,6 +869,9 @@ understand MUST be ignored.

## Token Verification by the Protocol Server

Here, `<iss-server>` is the authority of the `iss` URL: its host and
optional port, used as an OCM Server Address as defined in [OCM].

When a front-channel request presents a credential, the Protocol Server
MUST authorize it as follows:

Expand All @@ -881,22 +884,22 @@ instead: an `active` response supplies the fields (`iss`, `sub`, `aud`,
`exp`, `client_id`, `ocm_ip`) used in steps 4 to 6, and steps 2 and 3
are skipped; an inactive response means the request is rejected.
2. Resolve the signing key: fetch (or use a cached copy of) the OCM
Server's Discovery document at `https://<iss-host>/.well-known/ocm`,
Server's Discovery document at `https://<iss-server>/.well-known/ocm`,
read its `jwksUri` field, fetch the JWK Set from that URL, and select
the key matching the token's `kid` header parameter.
3. Verify the token signature and validity per [RFC9068]: the algorithm
MUST be an asymmetric algorithm matching the key, MUST NOT be `none`,
and the `exp` claim MUST be in the future. The claims `iss`, `sub`,
`aud`, `exp` and `client_id` MUST all be present.
4. Determine the integration mode:
* If a Share Record exists for the pair (host part of `iss`,
* If a Share Record exists for the pair (server address from `iss`,
`client_id` claim), the token is authorized against that record
(Provisioned Integration). Any `ocm_ip` claim in the token MUST be
ignored.
* Otherwise, if the verified token carries an `ocm_ip` claim and the
host part of `iss` is paired for Self-Contained Integration, or the
introspection response carries an `ocm_ip` member, the credential is
authorized against those claims.
server address from `iss` is paired for Self-Contained Integration,
or the introspection response carries an `ocm_ip` member, the
credential is authorized against those claims.
* Otherwise, reject the request. Because Share Records only come
into existence through signed back-channel requests from paired OCM
Servers, the `ocm_ip` claim is only honored for paired issuers, and
Expand All @@ -923,14 +926,14 @@ In Provisioned Integration, a valid signature and a matching Share
Record are not sufficient: the token MUST also be bound to the
identities stored in the record. The Protocol Server MUST verify that:

* the OCM Address formed as `<sub>@<iss-host>` equals the Share Record's
`owner`, and
* the OCM Address formed as `<sub>@<iss-server>` equals the Share
Record's `owner`, and
* the `aud` claim equals the Share Record's `shareWith`.

Comparison of OCM Addresses SHOULD be performed after canonicalising the
host part (lowercasing, removing any stray scheme prefix or trailing
slash); the identifier part is opaque and MUST be compared byte for
byte.
OCM Addresses MUST be compared as defined in the Terms section of [OCM]:
compare opaque identifiers byte for byte and complete server addresses
after lowercasing. Invalid server addresses MUST be rejected, rather
than repaired by stripping a scheme or trailing slash.

These checks ensure that an access token can only be used for the exact
Share it was issued for: a token legitimately issued to one Receiving
Expand All @@ -943,12 +946,12 @@ come from an introspection response that names a Share Record via
In Self-Contained Integration, and when serving from the `ocm_ip` member
of an introspection response, there is no stored record to compare
against: the credential itself is the authority, and the owner and the
Receiving Party are read directly from `<sub>@<iss-host>` and `aud`.
Receiving Party are read directly from `<sub>@<iss-server>` and `aud`.
The cross-checks above therefore do not apply; what remains is to
enforce the scope of the `ocm_ip` claim (protocol entries, permissions,
expiration) and, where the protocol concerned authenticates the
Receiving Party, to derive that identity from `aud` using the same
canonicalisation rules.
address comparison rules.

## Token Presentation per Protocol

Expand Down
17 changes: 9 additions & 8 deletions IETF-OCM-MLS.md
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,8 @@ The request has two REQUIRED query parameters:

- `userId` is the full OCM Address of the user whose KeyPackage is
requested.
- `senderDomain` is the FQDN of the requesting OCM Server.
- `senderDomain` is the requesting server's OCM Server Address
as defined in [OCM].

Response:

Expand Down Expand Up @@ -1345,13 +1346,13 @@ the application data:
~~~

Each entry identifies the share by its `providerId`, the group by its
OCM Address in `groupId`, and the intended Member Server by its FQDN in
`recipient`. A Member Server MUST ignore entries whose `recipient` does
not name itself. Upon accepting an entry, the Member Server replaces
the stored transport credential for that share; replacement follows the
same `(epoch, generation)` supersede rule as wrapped FKs
({{key-distribution}}). The sending server invalidates the old
credential once the rotation has been delivered.
OCM Address in `groupId`, and the intended Member Server by its OCM
Server Address in `recipient`. A Member Server MUST ignore entries whose
`recipient` does not name itself. Upon accepting an entry, the Member
Server replaces the stored transport credential for that share;
replacement follows the same `(epoch, generation)` supersede rule as
wrapped FKs ({{key-distribution}}). The sending server invalidates the
old credential once the rotation has been delivered.

Encrypting the credential update in the current epoch guarantees that
the removed member cannot read it, independent of transport protection:
Expand Down
99 changes: 56 additions & 43 deletions IETF-OCM.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,9 @@ related concepts from OAuth [RFC6749] and elsewhere:
* __Invite Sender OCM Server__ - The server holding an address book
used by the Invite Sender, to which details of the Invite Receiver are
to be added.
* __Invite String__ - An Invite Token and the FQDN of an Invite Sender
OCM Server joined by an `@`-sign, then encoded using base64url (the
URL- and filename-safe alphabet defined in [RFC4648], Section 5) with
* __Invite String__ - An Invite Token and the Invite Sender OCM Server
Address joined by an `@`-sign, then encoded using base64url (the URL-
and filename-safe alphabet defined in [RFC4648], Section 5) with
padding omitted.
* __Invite Token__ - A hard-to-guess string used in the Invite Flow,
generated by the Invite Sender OCM Server and linked uniquely to the
Expand All @@ -139,10 +139,10 @@ related concepts from OAuth [RFC6749] and elsewhere:

ocm-address = identifier "@" host [ ":" port]

"identifier" is an opaque, case-sensitive UTF-8 string. It is
separated from the host by the last "@" in the OCM Address. It is
possible to have multiple @-signs in a OCM-address, e.g. when an
email address is the local part of the address like
"identifier" is a non-empty, opaque, case-sensitive UTF-8 string. It
is separated from the host by the last "@" in the OCM Address. It is
possible to have multiple @-signs in a OCM-address, e.g. when an email
address is the local part of the address like
`nomen.nescio@example.org@cloud.example.org`.
"host" is an IP literal encapsulated within square brackets, an IPv4
address in dotted decimal form, or a registered name as described in
Expand All @@ -155,6 +155,19 @@ related concepts from OAuth [RFC6749] and elsewhere:
The OCM Server MUST be discoverable at the given host and optional
port via the Well-Known [RFC8615] path `/.well-known/ocm`. The OCM
Address MUST NOT contain a path.
* __OCM Server Address__ - The server part of an OCM Address:
its host and optional port, without an identifier or `@`. It has no
scheme, path, query or fragment. For example, `cloud.example.org`,
`cloud.example.org:8443`, `192.0.2.1` or `[2001:db8::1]:8443`.
Server addresses MUST be compared as complete strings after
lowercasing, preserving explicit ports and all other spelling.
OCM Addresses use this comparison for their server part and compare
identifiers byte for byte. An implementation MUST NOT strip a
scheme, infer a port, resolve a name or rewrite an IP spelling to
make identities match. Invalid input MUST be rejected before use;
an address that cannot be used for discovery MUST fail rather than
select another server. Discovered endpoint URLs locate services;
they do not change the server's identity.
* __OCM API Discovery__ - Process of evaluating properties of a Remote
Resource, after establishing contact with an OCM Server.
* __OCM Notification__ - A message from the Receiving Server to the
Expand Down Expand Up @@ -214,9 +227,9 @@ related concepts from OAuth [RFC6749] and elsewhere:
another OCM Server, based on out-of-band information, federation
membership or prior interactions, SHOULD be recorded in an internal
registry of trusted servers, that SHOULD be updated over time based
on new information. The registry SHOULD include the FQDN of the
trusted server and the public keys (JWK Set [RFC7517]) used for
HTTP Message Signatures. It MAY
on new information. The registry SHOULD include the
trusted server's OCM Server Address and the public keys
(JWK Set [RFC7517]) used for HTTP Message Signatures. It MAY
also include additional metadata such as the inviteAcceptDialog URL
or supported capabilities.
* __WAYF Page__ - A Where-Are-You-From page is a discovery service used
Expand Down Expand Up @@ -289,11 +302,11 @@ a description of the whole protocol in OpenAPI format.
# Establishing Contact

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
Receiving Server, it MUST establish the Receiving Party's OCM Address
(containing the Receiving Party's identifier and the Receiving Server's
OCM Server Address), 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,
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.

Expand Down Expand Up @@ -343,7 +356,7 @@ Share Creation Notification from an unknown Sending Party is received
the Invite Sender to create the Invite Message
* 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
Server Address, to the Invite Receiver
* 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
Expand All @@ -368,16 +381,16 @@ Acceptance Request MUST be a HTTP POST request:
* using `application/json` as the `Content-Type` HTTP request header
* its request body containing a JSON document representing an object
with the following string fields:
- REQUIRED: `recipientProvider` - FQDN of the Invite Receiver OCM
Server.
- REQUIRED: `recipientProvider` - OCM Server Address of the Invite
Receiver.
- REQUIRED: `token` - The Invite Token. The Invite Sender OCM Server
SHOULD recall which Invite Sender OCM Address this token was linked
to.
- REQUIRED: `userID` - The Invite Receiver's identifier at their OCM
Server.
- REQUIRED: `email` - Non-normative / informational; an email address
for the Invite Receiver. Not necessarily at the same FQDN as their
OCM Server.
for the Invite Receiver. Its domain need not match the
OCM Server Address.
- REQUIRED: `name` - Human-readable name of the Invite Receiver, as a
suggestion for display in the Invite Sender's address book
* using TLS
Expand Down Expand Up @@ -426,8 +439,8 @@ The Invite Acceptance Response SHOULD be a HTTP response:
- REQUIRED: `userID` - the Invite Sender's identifier at their OCM
Server
- REQUIRED: `email` - non-normative / informational; an email address
for the Invite Sender. Not necessarily at the same FQDN as their
OCM Server
for the Invite Sender. Its domain need not match the
OCM Server Address
- REQUIRED: `name` - human-readable name of the Invite Sender, as a
suggestion for display in the Invite Receiver's address book

Expand Down Expand Up @@ -483,7 +496,8 @@ To accept an invite, two pieces of information are required: a `token`
and a `provider`. There are two recognized formats:

* **Invite string format:**
The token and the provider’s FQDN, joined by an `@` sign and then
The token and the provider's OCM Server Address, joined by an `@`
sign and then
encoded using base64url (the URL- and filename-safe alphabet defined
in [RFC4648], Section 5) with padding omitted. Example:

Expand Down Expand Up @@ -547,7 +561,7 @@ delegated by the Sending Party, which is one of its registered users.

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
Receiving Server Address 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
Expand All @@ -570,7 +584,7 @@ The Sharing User MUST provide the following information:
* Protocol to be offered for access
* Sending Party's identifier
* Receiving Party's identifier
* Receiving Server FQDN
* Receiving Server Address
* OPTIONAL: Share Requirements
* OPTIONAL: Share Name
* OPTIONAL: Share Permissions
Expand All @@ -586,12 +600,12 @@ The next step is for the Sending Server to additionally discover:
`jwksUri` field

The Sending Server MAY first perform denylist and allowlist checks on
the FQDN.
the OCM Server Address.

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

If the FQDN passes the denylist and/or allowlist checks, but no details
If the server address passes these 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.

Expand All @@ -608,13 +622,13 @@ Index](#appendix-e-navigation-index).
## Process

At the start of the process, the Discovering Server has either an OCM
Address, or just an FQDN from for instance the `recipientProvider`
field of an Invite Acceptance Request.
Address, or an OCM Server Address from, for instance, the
`recipientProvider` field of an Invite Acceptance Request.

Step 1: In case it has an OCM Address, it SHOULD first extract `<fqdn>`
from it (the part after the last `@` sign).
Step 1: From an OCM Address, extract its OCM Server Address
(the part after the last `@` sign), called `<server-address>` below.
Step 2: The Discovering Server SHOULD attempt OCM API Discovery via a
HTTP GET request to `https://<fqdn>/.well-known/ocm`.
HTTP GET request to `https://<server-address>/.well-known/ocm`.
Step 3: If that results in a valid HTTP response with a valid JSON
response body within reasonable time, go to step 5.
Step 4: If not, fail. Implementations MAY fallback to HTTP instead
Expand Down Expand Up @@ -1342,14 +1356,14 @@ following hold true:

* the HTTP Message Signature is missing but the Sending Server
advertises the `http-sig` capability in the Discovery response
obtained from the FQDN part of the `sender` field in the request
obtained from the server part of the `sender` field in the request
body
* the Sending Server advertises the `http-sig` capability but its
Discovery response carries no `jwksUri`
* the HTTP Message Signature is missing
* the HTTP Message Signature is not valid (see [HTTP Message
Signatures](#http-message-signatures))
* no trusted JWK Set can be obtained for the FQDN part of the
* no trusted JWK Set can be obtained for the server part of the
`sender` field in the request body, via the `jwksUri` field of its
Discovery response
* that JWK Set contains no key whose `kid` equals the `keyid`
Expand Down Expand Up @@ -1398,10 +1412,10 @@ request:
* REQUIRED notificationType (string) - it MUST be one of the
registered values listed in the "OCM Notification Types"
registry (see [IANA Considerations](#iana-considerations)).
* REQUIRED senderDomain (string) - the FQDN of the sender. A Receiving
Server SHOULD use this information to verify the HTTP message
signature on the request, and it SHOULD also use it to validate the
underlying share or resource the notification is about.
* REQUIRED senderDomain (string) - the OCM Server Address of the
sender. A Receiving Server SHOULD use this information to verify
the HTTP message signature and validate the underlying share or
resource.
* OPTIONAL resourceType (string) - the type of the resource this
notification is about (e.g., `file`).
* OPTIONAL shareType (string) - the type of recipient this notification
Expand Down Expand Up @@ -1577,7 +1591,7 @@ To access the Resource, the Receiving Server MAY use multiple ways,
depending on the body of the Share Creation Notification and the
protocol required for access. The procedure is as follows:

1. The receiver MUST extract the OCM Server FQDN from the `sender`
1. The receiver MUST extract the OCM Server Address from `sender`
field of the received share, and MUST query the
[Discovery](#ocm-api-discovery) endpoint at that address: let
`<sender-ocm-path>` be the `resourceTypes[0].protocols.webdav` value
Expand Down Expand Up @@ -1692,7 +1706,7 @@ grant_type=authorization_code&client_id=receiver.example.org&code=\

The request MUST be signed using an HTTP Message Signature
[RFC9421]. The `client_id` identifies the Receiving Server and MUST be
set to its fully qualified domain name. The `code` parameter carries
set to its OCM Server Address. The `code` parameter carries
the authorization secret that was issued by the Sending Server in the
Share Creation Notification. It is allowed to send the additional
parameters defined in [RFC6749] for the `authorization_code` grant type,
Expand Down Expand Up @@ -1841,9 +1855,8 @@ Change Controller:
Reference or Description:
: An object representing an OCM address. The object contains:

- "address" (String, required): The OCM federated address in
format "user@provider" where provider is the FQDN of an
OCM-capable server.
- "address" (String, required): The full OCM Address, as
defined in [Terms](#terms).
- "trusted" (Boolean, optional): Whether shares from this address
are automatically accepted. Default: false.
- "source" (String, optional): How this address was established.
Expand Down Expand Up @@ -2614,7 +2627,7 @@ user such as if it was added via _Invites_ or direct entry.
* __email__: Contact email address (informational)
* __name__: Human-readable display name
* __userID__: The identifier of the contact at their OCM Server
* __provider__: The FQDN of the contact's OCM Server
* __provider__: The contact's OCM Server Address

### Relationships

Expand Down
Loading
Loading