mirror of https://github.com/moparisthebest/xeps
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
427 lines
22 KiB
427 lines
22 KiB
<?xml version='1.0' encoding='UTF-8'?> |
|
<!DOCTYPE xep SYSTEM 'xep.dtd' [ |
|
<!ENTITY % ents SYSTEM 'xep.ent'> |
|
%ents; |
|
]> |
|
<?xml-stylesheet type='text/xsl' href='xep.xsl'?> |
|
<xep> |
|
<header> |
|
<title>Pre-Authenticated Roster Subscription</title> |
|
<abstract>This document defines a protocol and URI scheme for pre-authenticated roster links that allow a third party to automatically obtain the user's presence subscription. The goal of this is to make onboarding of new XMPP IM contacts as easy as possible.</abstract> |
|
&LEGALNOTICE; |
|
<number>0379</number> |
|
<status>Proposed</status> |
|
<lastcall>2021-10-20</lastcall> |
|
<type>Standards Track</type> |
|
<sig>Standards</sig> |
|
<approver>Council</approver> |
|
<dependencies> |
|
<spec>XMPP Core</spec> |
|
<spec>RFC 5122</spec> |
|
<spec>XEP-0147</spec> |
|
</dependencies> |
|
<supersedes/> |
|
<supersededby/> |
|
<shortname>pars</shortname> |
|
<author> |
|
<firstname>Georg</firstname> |
|
<surname>Lukas</surname> |
|
<email>georg@op-co.de</email> |
|
<jid>georg@yax.im</jid> |
|
</author> |
|
<revision> |
|
<version>0.3.3</version> |
|
<date>2021-03-04</date> |
|
<initials>mw</initials> |
|
<remark><p>Cross-document editorial adjustments for inclusive language.</p></remark> |
|
</revision> |
|
<revision> |
|
<version>0.3.2</version> |
|
<date>2020-01-14</date> |
|
<initials>licaon-kter</initials> |
|
<remark>Fix a bunch of typos.</remark> |
|
</revision> |
|
<revision> |
|
<version>0.3.1</version> |
|
<date>2018-11-03</date> |
|
<initials>pep</initials> |
|
<remark>Fix a bunch of typos, batch-style.</remark> |
|
</revision> |
|
<revision> |
|
<version>0.3.0</version> |
|
<date>2018-10-01</date> |
|
<initials>XEP Editor (jsc)</initials> |
|
<remark>Defer due to lack of activity.</remark> |
|
</revision> |
|
<revision> |
|
<version>0.2.0</version> |
|
<date>2017-03-06</date> |
|
<initials>gl</initials> |
|
<remark><p>Change URI format, editing, add reference to XEP-0401.</p></remark> |
|
</revision> |
|
<revision> |
|
<version>0.1.2</version> |
|
<date>2017-02-16</date> |
|
<initials>gl</initials> |
|
<remark><p>Added "Usability Considerations", removed actual XMPP client, some text editing.</p></remark> |
|
</revision> |
|
<revision> |
|
<version>0.1.1</version> |
|
<date>2017-01-01</date> |
|
<initials>ssw</initials> |
|
<remark><p>Minor DTD and formatting fixes.</p></remark> |
|
</revision> |
|
<revision> |
|
<version>0.1.0</version> |
|
<date>2016-07-20</date> |
|
<initials>gl (XEP Editor: ssw)</initials> |
|
<remark><p>First draft.</p></remark> |
|
</revision> |
|
</header> |
|
<section1 topic='Introduction' anchor='intro'> |
|
<p>Romeo is an active XMPP IM (Instant Messaging) user. He convinces Juliet |
|
(who doesn't have an XMPP account yet) to install a client and |
|
register with some server. Now, Romeo only needs to create a mutual |
|
presence subscription with her, without yet knowing her JID.</p> |
|
<p>This specification allows Romeo to create an out-of-band link (URI) which, |
|
when opened in Juliet's (or another user's) client, will:</p> |
|
<ul> |
|
<li>Add Romeo to Juliet's roster (with a display name optionally specified by Romeo)</li> |
|
<li>Add Juliet to Romeo's roster (without a predefined display name)</li> |
|
<li>Establish a mutual presence subscription between Romeo and Juliet</li> |
|
</ul> |
|
<p>The perceivable effect is that with a single click, Romeo and Juliet |
|
become "friends" in terms of XMPP presence subscription.</p> |
|
</section1> |
|
<section1 topic='Requirements' anchor='reqs'> |
|
<p>This specification makes use of XMPP URIs. The basic URI scheme for XMPP |
|
is defined in &rfc5122; and extended in &xep0147; to support different |
|
actions like "roster" for roster addition and "subscribe" for presence |
|
subscription. |
|
</p> |
|
</section1> |
|
<section1 topic='Pre-Authenticated Roster Subscription' anchor='pars'> |
|
<p>The process of mutual roster addition and subscription involves multiple |
|
steps:</p> |
|
<ol> |
|
<li>Generation of invitation link</li> |
|
<li>Out-of-band transmission and presentation of the link</li> |
|
<li>Subscription request to the user by the link receiver (new contact)</li> |
|
<li>Approval by the user and mutual subscription request</li> |
|
<li>Approval by the new contact</li> |
|
</ol> |
|
<p>The general idea of the protocol and the details of the individual steps |
|
are outlined in the following.</p> |
|
<section2 topic='General Idea' anchor='general_idea'> |
|
<p>As Romeo doesn't know Juliet's JID, he needs to send an out-of-band |
|
invitation. Later, his client needs to match an incoming subscription |
|
request to this invitation, so it can perform a secure automatic roster |
|
addition and subscription approval. This matching is accomplished by |
|
means of an authentication token, which is generated by Romeo's client, |
|
added to the invitation link and then carried over into the subscription |
|
request eventually made by Juliet's client. Romeo's client can then |
|
compare the token received in a subscription request to the list of |
|
issued tokens, and automatically approve the subscription.</p> |
|
<code caption='Successful PARS Protocol Flow'><![CDATA[ |
|
Romeo mongatague.net capulet.net Juliet |
|
| | | | |
|
| Send out-of-band invitation link | |
|
| xmpp:romeo@montague.net?roster;preauth=token | |
|
|- - - - - - - - - - - - - - - - - - - - - - ->| |
|
| | | roster add | |
|
| | |<--------------| |
|
| presence subscription request w/ token | |
|
| <presence><preauth token="..."/></presence> | |
|
|<---------------------------------------------| |
|
| (token validation check) | | |
|
| presence subscribed | | |
|
|--------------------------------------------->| |
|
| roster add | | | |
|
|------------->| | | |
|
| presence subscription request| | |
|
|--------------------------------------------->| |
|
| | (auto approval) | |
|
| | presence subscribed | |
|
|<---------------------------------------------| |
|
]]></code> |
|
</section2> |
|
<section2 topic='Generation of Invitation Link' anchor='link_generation'> |
|
<p>Whenever Romeo wishes to invite somebody to his roster, his client will |
|
generate an invitation link that contains a new authentication token. |
|
This document extends the "roster" URI action defined in <cite>XEP-0147</cite> with |
|
a new key-value parameter named "preauth" to store the generated token. |
|
Romeo's client will create an <strong>xmpp:</strong> link containing Romeo's JID, the |
|
"roster" action, the "preauth" parameter with the token value, and |
|
optionally a "name" parameter with the suggested display name. |
|
</p> |
|
<example caption='Invitation Link with Roster Action and Authentication Token'><![CDATA[ |
|
xmpp:romeo@montague.net?roster;preauth=1tMFqYDdKhfe2pwp;name=Romeo+Montague |
|
]]></example> |
|
<p> |
|
If the "preauth" parameter is present, the processing client is supposed |
|
not only to add the user to the roster, but also to automatically send a |
|
subscription request containing the authentication token. |
|
</p> |
|
|
|
<p></p> |
|
|
|
<p><strong>Server-side implementation:</strong> it is |
|
possible (but out-of-scope for this document), to let the user's server |
|
handle generation of links as well as automatic approval of qualified |
|
subscription requests. One such approach is documented in &xep0401;.</p> |
|
|
|
</section2> |
|
|
|
<section2 topic='Out-of-band Transmission and Presentation of the Link' anchor='link_transmission'> |
|
<p>As Romeo doesn't know Juliet's JID in advance, he needs to use an out-of-band method (like e-mail, QR codes or NFC) to transmit the invitation link to Juliet. While these methods allow transmission of <strong>xmpp:</strong> URIs, there is no mechanism to ensure that Juliet actually has a client installed that can open the URI.</p> |
|
<p>One way to solve this problem is to present Juliet with a web-based landing page that contains the following elements:</p> |
|
<ul> |
|
<li>A short text that this is an XMPP invitation from Romeo.</li> |
|
<li>A client recommendation (based on the detected web browser/OS) with download links.</li> |
|
<li>A prominent button that activates the actual <strong>xmpp:</strong> link.</li> |
|
</ul> |
|
<p>There are multiple options where such a landing page could be hosted:</p> |
|
<ol> |
|
<li><strong>XSF:</strong> a central place would provide a common ground |
|
for a curated client list and ensure long-term availability. However, |
|
the operator would be able to collect metadata and abuse authentication tokens.</li> |
|
<li><strong>Client developer:</strong> the developer of Romeo's client can |
|
provide a landing page for invitation requests created with this |
|
client. This is a feasible short-term solution and allows to recommend |
|
the same client as used by the link sender. However, it shares the |
|
privacy objections of the XSF solution and can not guarantee |
|
long-term availability of the service. If the client development shuts |
|
down, invitation links created with the client will cease working.</li> |
|
<li><strong>User's server:</strong> this is the optimal long-term |
|
solution, as the user's server is already entrusted with the relevant |
|
metadata and will exist at least as long as the user's account on that |
|
server. However, this requires an additional server component to query |
|
for invitation URIs and a web server hosting the landing page. |
|
Furthermore, the server operator needs to maintain the list of |
|
recommended clients.</li> |
|
</ol> |
|
<example caption='Developer-Hosted Landing Page Generated with Fictitious JuicyXMPP Client'><![CDATA[ |
|
https://juicyxmpp.example/i/#romeo@montague.net?roster;preauth=1tMFqYDdKhfe2pwp;name=Romeo+Montague |
|
]]></example> |
|
<p>A possible screen representation of the landing page would be:</p> |
|
<div class="example"> |
|
<p><strong><em>Romeo Montague</em> has invited you to chat</strong></p> |
|
|
|
<p><strong><link url='xmpp:romeo@montague.net?roster;preauth=1tMFqYDdKhfe2pwp;name=Romeo%20Montague'>Add "Romeo Montague"</link></strong></p> |
|
<p>If this link does not work, you need to install and configure |
|
an XMPP client. Please visit this page again afterwards. Choose one of |
|
these for your <em>Tomato OS</em>:</p> |
|
<ul> |
|
<li><strong>JuicyXMPP</strong> (link to XMPP client)</li> |
|
<li><strong>VegetableChat</strong> (link to XMPP client)</li> |
|
</ul> |
|
<p>Check the <link url='http://xmpp.org/software/clients.html'>full list of XMPP clients</link>.</p> |
|
<p>No further action is required if you do not know <em>Romeo Montague</em> or do not want to chat with them.</p> |
|
<p>XMPP is a provider-independent form of instant messaging. That means |
|
you can pick from many different clients and have a free choice of |
|
server operators to communicate with <em>Romeo Montague</em>.</p> |
|
|
|
</div> |
|
|
|
</section2> |
|
|
|
<section2 topic='Subcription Request to the User by the Link Receiver (New Contact)' anchor='link_transmission'> |
|
<p>When Juliet opens the <strong>xmpp:</strong> URI (or the according client-supported |
|
landing page URI) in her client, the client should perform the usual |
|
roster addition action, i.e. display a dialog allowing to edit the entry |
|
or to cancel the process. If Juliet completes the roster addition, the |
|
client SHOULD also send a subscription request to Romeo. This request |
|
SHOULD contain a 'preauth' element containing the authentication token |
|
from the invitation link. |
|
</p> |
|
<example caption='Subscription Request with Pre-Authenticated Roster Subscription Element'><![CDATA[ |
|
<presence to='romeo@montague.net' type='subscribe'> |
|
<preauth xmlns='urn:xmpp:pars:0' token='1tMFqYDdKhfe2pwp' /> |
|
</presence> |
|
]]></example> |
|
<p>If Juliet's server supports <link |
|
url='http://xmpp.org/rfcs/rfc6121.html#sub-preapproval'>subscription |
|
pre-approval</link>, the client SHOULD additionally pre-approve Romeo: |
|
</p> |
|
<example caption='Juliet Pre-approves Romeo'><![CDATA[ |
|
<presence to='romeo@montague.net' type='subscribed' /> |
|
]]></example> |
|
<p>If Juliet's server does not indicate pre-approval support, her client |
|
SHOULD store Romeo's JID in a local auto-approval list, together |
|
with an appropriate expiration time. |
|
</p> |
|
</section2> |
|
|
|
<section2 topic='Approval by the User and Mutual Subscription Request' anchor='sub_approval'> |
|
<p>When Romeo's client receives a subscription request containing a |
|
'preauth' element, it needs to extract the authentication token and |
|
check if the token is a valid one and was previously issued by the client |
|
(see security considerations below).</p> |
|
<example caption='Subscription Request With Tokens Received by Romeo'><![CDATA[ |
|
<presence to='romeo@montague.net' from='juliet@capulet.net' type='subscribe'> |
|
<preauth xmlns='urn:xmpp:pars:0' token='1tMFqYDdKhfe2pwp' /> |
|
</presence> |
|
]]></example> |
|
<p>If the token is considered valid, the client SHOULD automatically approve |
|
the subscription request, add the sender of the subscription request to |
|
the roster and send a subscription request of its own.</p> |
|
<example caption='Automatic Approval and Response Subscription Request'><![CDATA[ |
|
<presence to='juliet@capulet.net' type='subscribed' /> |
|
<presence to='juliet@capulet.net' type='subscribe' /> |
|
]]></example> |
|
|
|
</section2> |
|
|
|
<section2 topic='Approval by the New Contact' anchor='sub_mutual_approval'> |
|
<p>If Juliet's server supports pre-approval, it will automatically handle the |
|
incoming subscription request and issue a roster push. Otherwise, Juliet's |
|
client will receive the subscription request:</p> |
|
<example caption='Mutual Subscription Request'><![CDATA[ |
|
<presence from='romeo@montague.net' to='juliet@capulet.net' type='subscribe' /> |
|
]]></example> |
|
<p>Juliet's client MUST ensure that the sender JID is contained in the |
|
auto-approval list before automatically approving the request. |
|
Otherwise, it has to fallback to the normal subscription approval |
|
process.</p> |
|
|
|
</section2> |
|
</section1> |
|
<section1 topic='Business Rules' anchor='rules'> |
|
<section2 topic='Fallback to Manual Process' anchor='rules_fallback'> |
|
<p>An implementation of this protocol MUST allow for a "graceful |
|
degradation" to the manual subscription approval process. If a client |
|
receives a malformed or unknown 'preauth' token, it MUST ignore it and act |
|
as if no preauth token was contained.</p> |
|
</section2> |
|
|
|
<section2 topic='No Expectation of Immediate Approval' anchor='rules_expectation'> |
|
<p>When sending a pre-authenticated subscription request, the contact's |
|
client MUST NOT expect an immediate successful approval. If the user's |
|
issuing client is currently offline, or if the token has expired, a manual |
|
approval will be performed. Therefore, the contact's client should use the |
|
same mechanism as before to indicate an unidirectional subscription. |
|
</p> |
|
</section2> |
|
</section1> |
|
<section1 topic='Security Considerations' anchor='security'> |
|
<section2 topic='Token Generation' anchor='security_token'> |
|
<p>As the authentication token grants automatic addition to |
|
Romeo's roster and automatic approval of presence subscription, |
|
the token SHOULD be created with a cryptographically secure random |
|
number generator <note>See for example <tt><link |
|
url='https://lwn.net/Articles/606141/'>getrandom(2)</link></tt>, |
|
<tt><link |
|
url='https://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html'>SecureRandom</link></tt> |
|
or <tt>/dev/urandom</tt>. More information about the randomness |
|
requirements for security can be found in &rfc4086;</note> and |
|
provide sufficient entropy to make brute-force attacks |
|
infeasible. It is suggested to generate at least 80 bits of |
|
entropy, and to use an encoding that can be easily encoded as part |
|
of an URI (e.g. Base-32).</p> <p>It is possible to use a different token |
|
generation scheme like &saml; or JWT (&rfc7519;). |
|
In such a case, the issuer must ensure a comparable security level and |
|
limit token reuse.</p> |
|
</section2> |
|
<section2 topic='Checking Token Validity' anchor='security_validity'> |
|
<p>To limit the potential for abuse, the token SHOULD be limited in as follows:</p> |
|
<ul> |
|
<li><strong>Usage:</strong> in the typical scenario, each token may only |
|
be used once. While it is possible for a client to generate a token for |
|
multiple uses (like for embedding it in a contact card), the |
|
conventional manual roster management should be used for public |
|
invitation links.</li> |
|
<li><strong>Time:</strong> each token MUST have a limited validity time. |
|
As the token is transmitted out-of-band, it should provide sufficient |
|
reaction time, e.g. one week. This time limit also allows the issuer to |
|
delete expired tokens.</li> |
|
<li><strong>Identity:</strong> if the JID of the token receiver is known |
|
in advance, the token sender MUST NOT allow a different JID to redeem |
|
this token.</li> |
|
</ul> |
|
<p>If a token is considered invalid (due to failing any of the above |
|
conditions, or for other reasons), a client MUST fall back to manual |
|
roster addition and manual subscription approval. |
|
</p> |
|
</section2> |
|
<section2 topic='Interception of Links' anchor='security_intercept'> |
|
<p>A Monkey-in-the-Middle attacker who gains access to the invitation link |
|
can manipulate its fields or redeem the link themselves. However, this is |
|
true for all communication performed using the chosen medium and is out of |
|
scope for this document.</p> |
|
<p>Ideally, Romeo's client should highlight automatically-added roster items |
|
and provide an easy mechanism to remove them and cancel their |
|
subscription.</p> |
|
</section2> |
|
<section2 topic='Display Names' anchor='security_display'> |
|
<p>An attacker can lure the user by providing an invitation link with a |
|
'name' parameter that does not match the JID. Therefore, a client SHOULD |
|
always display both the JID and the proposed display name when adding a |
|
roster item.</p> |
|
<p>When the user's client automatically approves a subscription, it SHOULD |
|
add the new contact to the roster without a 'name' or with the 'name' |
|
equal to the JID, to prevent impersonation attacks.</p> |
|
</section2> |
|
</section1> |
|
<section1 topic='Usability Considerations' anchor='usability'> |
|
<section2 topic='Use of Multiple Clients' anchor='rules_multiclient'> |
|
<p>If a user is logged in with multiple clients, some of their clients will |
|
receive a subscription request with an unknown token. In this case, a client |
|
MAY delay the user notification for a short time, to allow another logged-in |
|
client to automatically handle the subscription request.</p> |
|
</section2> |
|
|
|
<section2 topic='Opening the Landing Page in an App' anchor='rules_multiclient'> |
|
<p>Some mobile device platforms allow an app to register itself as a |
|
handler for certain URIs. This allows an XMPP client to register for <strong>xmpp:</strong> |
|
URIs, but also to redirect handling of certain HTTP/HTTPS URIs. A mobile |
|
client SHOULD register for the associated landing page URIs and properly |
|
handle the contained invitations. For example, the JuicyXMPP client should |
|
register a handler for <strong>https://juicyxmpp.example/i/*</strong>, and present |
|
the "Add to roster" dialog if such a link is opened. A client MAY register |
|
for the landing page URIs of other providers after obtaining the |
|
operators' approval. |
|
</p> |
|
</section2> |
|
<section2 topic='Invitation Link Volatility' anchor='rules_volatile'> |
|
<p>By default, Romeo's client should generate personal invitation links |
|
that can only be redeemed once, and only for a limited time. This fact |
|
SHOULD be indicated by the client UI to Romeo.</p> |
|
<p>If a client allows customization of the validity time or the number of |
|
uses for a given invitation token, it SHOULD provide clear language |
|
to indicate that.</p> |
|
</section2> |
|
<section2 topic='Tagging of Auto-Added Contacts' anchor='rules_group'> |
|
<p>When a new contact is added automatically by the client, it SHOULD |
|
indicate this fact to the user, and allow the user to rename / group |
|
the contact appropriately. One possible way to achieve this is by |
|
putting all auto-added contacts into a special roster group, and by |
|
automatically removing this group on the first manual edit of the |
|
contact.</p> |
|
<p>In this case, the roster group should be named by the client according |
|
to the user's locale settings. However, this approach might lead to |
|
different clients using different group names, resulting in multiple |
|
roster groups with the same goal.</p> |
|
</section2> |
|
</section1> |
|
<section1 topic='IANA Considerations' anchor='iana'> |
|
<p>This document requires no interaction with &IANA;.</p> |
|
</section1> |
|
<section1 topic='XMPP Registrar Considerations' anchor='registrar'> |
|
<p>Include the "urn:xmpp:pars:0" namespace in the registry of protocol |
|
namespaces. Include "preauth" as an additional key-value parameter to the |
|
roster query action.</p> |
|
<code caption='New Roster Query Action Parameter'><![CDATA[ |
|
<querytype> |
|
<name>roster</name> |
|
... |
|
<key> |
|
<name>preauth</name> |
|
<desc>the token used to obtain an automatic approval from the target JID</desc> |
|
</key> |
|
</querytype> |
|
]]></code> |
|
</section1> |
|
<section1 topic='XML Schema' anchor='schema'> |
|
<p>REQUIRED for protocol specifications.</p> |
|
</section1> |
|
</xep>
|
|
|