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.
482 lines
20 KiB
482 lines
20 KiB
<?xml version='1.0' encoding='UTF-8'?> |
|
<!DOCTYPE xep SYSTEM 'xep.dtd' [ |
|
<!ENTITY % ents SYSTEM 'xep.ent'> |
|
<!ENTITY MOVED "<moved/>"> |
|
%ents; |
|
]> |
|
<?xml-stylesheet type='text/xsl' href='xep.xsl'?> |
|
<xep> |
|
<header> |
|
<title>Moved</title> |
|
<abstract>This document defines an XMPP protocol extension that enables a user to inform its contacts about a change in JID.</abstract> |
|
&LEGALNOTICE; |
|
<number>0283</number> |
|
<status>Experimental</status> |
|
<type>Standards Track</type> |
|
<sig>Standards</sig> |
|
<approver>Council</approver> |
|
<dependencies> |
|
<spec>XMPP Core</spec> |
|
</dependencies> |
|
<supersedes> |
|
</supersedes> |
|
<supersededby/> |
|
<shortname>moved</shortname> |
|
&mwild; |
|
<revision> |
|
<version>0.2.0</version> |
|
<date>2021-07-20</date> |
|
<initials>mw</initials> |
|
<remark><p>Re-write the flow with a more focused approach.</p></remark> |
|
</revision> |
|
<revision> |
|
<version>0.1.1</version> |
|
<date>2018-08-06</date> |
|
<initials>pep</initials> |
|
<remark><p>Fix trivial typo</p></remark> |
|
</revision> |
|
<revision> |
|
<version>0.1</version> |
|
<date>2010-06-16</date> |
|
<initials>psa</initials> |
|
<remark><p>Initial published version.</p></remark> |
|
</revision> |
|
<revision> |
|
<version>0.0.7</version> |
|
<date>2010-06-09</date> |
|
<initials>tp</initials> |
|
<remark> |
|
<p>Modified syntax to use 'old' and 'new' attributes.</p> |
|
</remark> |
|
</revision> |
|
<revision> |
|
<version>0.0.6</version> |
|
<date>2010-06-07</date> |
|
<initials>tp</initials> |
|
<remark> |
|
<ul> |
|
<li>Update ordering so that it recommends sending the unsubscribe/unsubscribed, before, sending the subscribe</li> |
|
<li>Add section documenting what happens when a contact is offline when the unsubscribe/unsubscribed/subscribe stanzas are sent.</li> |
|
<li>Added an example about a hacker sending an unsolicited subscribe by guessing a roster entry.</li> |
|
</ul> |
|
</remark> |
|
</revision> |
|
<revision> |
|
<version>0.0.5</version> |
|
<date>2010-06-02</date> |
|
<initials>tp</initials> |
|
<remark> |
|
<p>Added one-way subscription section</p> |
|
</remark> |
|
</revision> |
|
<revision> |
|
<version>0.0.4</version> |
|
<date>2010-05-30</date> |
|
<initials>tp</initials> |
|
<remark> |
|
<p>Change MUST NOT to SHOULD NOT for clients auto-subscribing back; differentiate between inbound and outbound subscriptions.</p> |
|
</remark> |
|
</revision> |
|
<revision> |
|
<version>0.0.3</version> |
|
<date>2010-06-02</date> |
|
<initials>tp</initials> |
|
<remark><p>Add one-way subscription comments.</p></remark> |
|
</revision> |
|
<revision> |
|
<version>0.0.2</version> |
|
<date>2010-05-25</date> |
|
<initials>tp</initials> |
|
<remark><p>Minor tweaks.</p></remark> |
|
</revision> |
|
<revision> |
|
<version>0.0.1</version> |
|
<date>2010-05-22</date> |
|
<initials>tp</initials> |
|
<remark><p>First draft.</p></remark> |
|
</revision> |
|
</header> |
|
<section1 topic='Introduction' anchor='intro'> |
|
<p>There are a variety of reasons why a user may wish to change |
|
their JID. For example, a surname change because of marriage or simply |
|
an easier JID to remember. Another common reason is that the provider goes |
|
out of service (with a notice).</p> |
|
|
|
<p>This XEP defines an approach for communicating that your JID has |
|
moved to a new JID, extending the existing subscription protocol documented |
|
in &xmppim;. The steps outlined here may be done either through a client |
|
or automated by a server.</p> |
|
</section1> |
|
|
|
<section1 topic='Requirements' anchor='reqs'> |
|
<p>This document aims to satisfy the following requirements:</p> |
|
<ul> |
|
<li>Users should be able to notify their contacts of a change of address.</li> |
|
<li>Contacts should be able to verify that such a notification is legitimate, to prevent malicious actors from spoofing notifications.</li> |
|
<li>It should be possible for a contact's server to automatically update the contact's roster for seamless migrations.</li> |
|
<li>In the absence of a contact's support for this protocol, it should fall back to a simple manual subscription approval.</li> |
|
</ul> |
|
</section1> |
|
|
|
<section1 topic='Glossary' anchor='glossary'> |
|
<dl> |
|
<di> |
|
<dt>Moved notification</dt> |
|
<dd>An XML <moved/> element sent to a contact to inform them that |
|
the user is moving to a new address. |
|
</dd> |
|
</di> |
|
<di> |
|
<dt>Moved statement</dt> |
|
<dd>An XML <moved/> element published by the user on their old |
|
account. It is used by contacts to verify that moved notifications |
|
are genuine. |
|
</dd> |
|
</di> |
|
</dl> |
|
</section1> |
|
|
|
<section1 topic='Use Cases' anchor='usecases'> |
|
<p>We start with the situation where the user, let's call them Juliet, has two accounts - |
|
her original account <tt>juliet@im.example.net</tt> and a shiny new account on her personal |
|
domain, <tt>juliet@capulet.example</tt>.</p> |
|
<p>Juliet would like to migrate all her data and contacts to her new account, with minimal |
|
disruption.</p> |
|
<section2 topic='User publishes moved statement' anchor='publish-statement'> |
|
<p>Before notifying contacts of the move, Juliet must connect to her old |
|
account and publish a "statement" that the account is no longer in |
|
use. This statement includes the address of her new account. |
|
</p> |
|
<p>The statement should be posted to a PEP node with the name 'urn:xmpp:moved:1'. The |
|
payload should be a <moved/> element in the 'urn:xmpp:moved:1' namespace. This |
|
element should in turn contain a single <new-jid/> element with the user's new JID |
|
as its text content.</p> |
|
|
|
<example caption='Juliet's client publishes a moved statement on her old account'><![CDATA[ |
|
<iq from='juliet@im.example.net/VR0sAGae' |
|
type='set' |
|
id='pub1'> |
|
<pubsub xmlns='http://jabber.org/protocol/pubsub'> |
|
<publish node='urn:xmpp:moved:1'> |
|
<item id='current'> |
|
<moved xmlns='urn:xmpp:moved:1'> |
|
<new-jid>juliet@capulet.example</new-jid> |
|
</moved> |
|
</item> |
|
</publish> |
|
</pubsub> |
|
</iq> |
|
]]></example> |
|
</section2> |
|
<section2 topic='User notifies contacts of move' anchor='publish-notification'> |
|
<p>After publishing a moved statement on her old account, Juliet proceeds |
|
to notify her contacts about the move.</p> |
|
|
|
<p>Juliet connects to her new account, and sends a subscription request to |
|
each of her contacts. These subscription requests MUST contain a <moved/> |
|
element in the 'urn:xmpp:moved:1' namespace. This element contains a single |
|
<old-jid/> element with the old JID as its text content.></p> |
|
|
|
<example caption='Juliet sends a subscription request to Romeo from her new account'><![CDATA[ |
|
<presence type='subscribe' to='romeo@montague.example' id='sub1'> |
|
<moved xmlns='urn:xmpp:moved:1'> |
|
<old-jid>juliet@im.example.net</old-jid> |
|
</moved> |
|
</presence> |
|
]]></example> |
|
</section2> |
|
|
|
<section2 topic='Contact receives subscription request with moved notification' anchor='receive-notification-client'> |
|
<p>Juliet's contact, Romeo, receives the subscription request from Juliet's |
|
new JID. At this point Romeo has not verified that the new account |
|
actually belongs to Juliet, and MUST perform such verification before |
|
acting on the request any differently to usual.</p> |
|
|
|
<p>If the value of <old-jid/> is not in the roster with an approved |
|
incoming subscription ('from' or 'both'), the <moved/> element |
|
MUST be ignored entirely.</p> |
|
|
|
<p>To verify the request, Romeo makes a request to the JID specified in |
|
<old-jid/> (which MUST be a bare JID) to fetch a published move |
|
statement.</p> |
|
|
|
<example caption='Romeo requests a moved statement from Juliet's old account'><![CDATA[ |
|
<iq type='get' |
|
from='romeo@capulet.example/laptop' |
|
to='juliet@im.example.net' |
|
id='83hKgF'> |
|
<pubsub xmlns='http://jabber.org/protocol/pubsub'> |
|
<items node='urn:xmpp:moved:1'> |
|
<item id='current'/> |
|
</items> |
|
</pubsub> |
|
</iq> |
|
]]></example> |
|
|
|
<p>On success, Juliet's server will return the moved statement that Juliet published.</p> |
|
|
|
<example caption='Juliet's old server returns the published moved statement to Romeo'><![CDATA[ |
|
<iq type='result' |
|
from='juliet@im.example.net' |
|
to='romeo@capulet.example/laptop' |
|
id='83hKgF'> |
|
<pubsub xmlns='http://jabber.org/protocol/pubsub'> |
|
<items node='urn:xmpp:moved:1'> |
|
<item id='current'> |
|
<moved xmlns='urn:xmpp:moved:1'> |
|
<new-jid>juliet@capulet.example</new-jid> |
|
</moved> |
|
</item> |
|
</items> |
|
</pubsub> |
|
</iq> |
|
]]></example> |
|
|
|
<p>Romeo MUST now verify that the received subscription request was from |
|
the same bare JID contained in the <new-jid/> element in the moved |
|
statement. If the JIDs do not match, or if there was an error fetching |
|
the moved statement (except for "gone" - see note below), the |
|
<moved/> element in the incoming subscription request MUST be |
|
ignored entirely.</p> |
|
|
|
<p class="box"> |
|
<strong>Note:</strong> As a special case, if the attempt to retrieve the |
|
moved statement results in an error with the <gone/> condition as |
|
defined in RFC 6120, and that <gone/> element contains a valid |
|
XMPP URI (e.g. <tt>xmpp:user@example.com</tt>), then the error response |
|
MUST be handled equivalent to a <moved/> statement containing a |
|
<new-jid/> element with the JID provided in the URI (e.g. |
|
<tt>user@example.com</tt>). |
|
</p> |
|
|
|
|
|
<p>Upon successful verification, Romeo's client may present an appropriate |
|
user interface, informing about Juliet's change of address, and a prompt |
|
to accept the subscription request from the new address. On the user's |
|
approval of such a subscription request, the client will typically want |
|
to also send a subscription request to the contact's new JID to establish |
|
a mutual subscription.</p> |
|
|
|
<p>Due to the potential for races between multiple clients connected to |
|
the same account, it is NOT RECOMMENDED for a client to automatically |
|
act upon migration notifications, but instead await manual interaction |
|
from the user. As with any inbound subscription request it SHOULD pay |
|
attention to roster pushes related to the contact, and update the UI |
|
appropriately if the new contact address is authorized from another |
|
device.</p> |
|
</section2> |
|
|
|
<section2 topic='Server-side processing of inbound moved notification' anchor='receive-notification-server'> |
|
<p>It is not required for Romeo's server to support this specification. |
|
However if Romeo's server does understand this extension, it SHOULD |
|
handle the inbound subscription request on behalf of Romeo's clients. |
|
This improves the user experience for Romeo, especially when he has |
|
multiple devices.</p> |
|
|
|
<p>Broadly the server should follow exactly the same process as a client |
|
would. Specifically: |
|
</p> |
|
<ol> |
|
<li>Receive subscription request with 'moved' payload.</li> |
|
<li>Verify that the old JID has an approved subscription to the user (i.e. a subscription of 'both' or 'from').</li> |
|
<li>Request moved statement from the old account JID.</li> |
|
<li>Verify that the new JID in the moved statement matches the 'from' of the subscription request.</li> |
|
</ol> |
|
|
|
<example caption='Romeo's server requests a moved statement from Juliet's old account'><![CDATA[ |
|
<iq type='get' |
|
from='romeo@capulet.example' |
|
to='juliet@im.example.net' |
|
id='83hKgF'> |
|
<pubsub xmlns='http://jabber.org/protocol/pubsub'> |
|
<items node='urn:xmpp:moved:1'> |
|
<item id='current'/> |
|
</items> |
|
</pubsub> |
|
</iq> |
|
]]></example> |
|
|
|
<example caption='Juliet's old server returns the published moved statement to Romeo's server'><![CDATA[ |
|
<iq type='result' |
|
from='juliet@im.example.net' |
|
to='romeo@capulet.example/laptop' |
|
id='83hKgF'> |
|
<pubsub xmlns='http://jabber.org/protocol/pubsub'> |
|
<items node='urn:xmpp:moved:1'> |
|
<item id='current'> |
|
<moved xmlns='urn:xmpp:moved:1'> |
|
<new-jid>juliet@capulet.example</new-jid> |
|
</moved> |
|
</item> |
|
</items> |
|
</pubsub> |
|
</iq> |
|
]]></example> |
|
|
|
<p>If verification fails (e.g. due to a missing or incorrect moved |
|
statement), the server MUST ignore the <moved/> element in the |
|
subscription request, and process the stanza as a normal subscription |
|
request. It MUST NOT strip the <moved/> element before forwarding, |
|
even if verification fails.</p> |
|
|
|
<p>Upon successful verification, the server MUST NOT forward the stanza to |
|
Romeo's clients, but instead MUST create a roster entry for the new JID |
|
with a subscription of 'from' (sending out the appropriate roster push), |
|
and then auto-reply to the subscription request with a presence of type |
|
'subscribed'.</p> |
|
|
|
<example caption='Romeo's server notifies Romeo about the new roster entry'><![CDATA[ |
|
<iq id='a78b4q6ha463' |
|
to='romeo@montague.example/orchard' |
|
type='set'> |
|
<query xmlns='jabber:iq:roster'> |
|
<item jid='juliet@capulet.example'' |
|
subscription='from'/> |
|
</query> |
|
</iq> |
|
]]></example> |
|
|
|
<p>After authorizing the new JID, the server should revoke the presence |
|
subscription of the old account.</p> |
|
|
|
<example caption='Romeo's server notifies Juliet's old account about unsubscription'><![CDATA[ |
|
<presence to='juliet@im.example.net' type='unsubscribed'/> |
|
]]></example> |
|
|
|
<example caption='Romeo's server notifies Romeo's clients about the old roster entry'><![CDATA[ |
|
<iq id='a78b4q6ha463' |
|
to='romeo@montague.example/orchard' |
|
type='set'> |
|
<query xmlns='jabber:iq:roster'> |
|
<item jid='juliet@im.example.net'' |
|
subscription='to'/> |
|
</query> |
|
</iq> |
|
]]></example> |
|
|
|
<p>Finally, if the old JID was in the user's roster with a subscription of 'both', the |
|
server MUST also send a presence of type 'subscribe' to the new JID in |
|
order to seek establishment of a mutual subscription.</p> |
|
|
|
<example caption='Romeo's server sends subscription request to Juliet's new JID'><![CDATA[ |
|
<presence type='subscribe' id='uc51xs63' from='romeo@montague.example' to='juliet@capulet.example'/> |
|
]]></example> |
|
|
|
</section2> |
|
|
|
</section1> |
|
|
|
<section1 topic='Implementation Notes' anchor='impl'> |
|
<section2 topic='Lifetime of moved statement' anchor='impl-lifetime'> |
|
<p>The moved statement is required for contacts to automatically verify |
|
the authenticity of moved notifications. After publishing a moved |
|
statement, the user should keep the statement published and the account |
|
active for long enough for contacts to switch to the user's new account.</p> |
|
<p>It is not necessary to remain connected to the old account during the |
|
transition period. However the account must not be deleted, and the |
|
server must be available.</p> |
|
<p>In the event that the move statement is unpublished, the account is deleted, |
|
or the server becomes unavailable, any contacts that have not yet transitioned |
|
to the user's new JID will be unable to verify the migration. Those contacts |
|
will have to manually approve the subscription from the user's new address.</p> |
|
<p>Migration progress of contacts is obervable through subscription revocations to |
|
the old account, and subscription approvals to the new account.</p> |
|
</section2> |
|
<section2 topic='Alternative verification methods' anchor='impl-alt-verify'> |
|
<p>Future revisions of this document, or alternative documents, may define |
|
alternative verification methods. Such methods SHOULD be communicated via |
|
child elements of <moved/> in an appropriate namespace. As is usual |
|
throughout XMPP, entities MUST ignore unknown child elements of |
|
<moved/> in unrecognised namespaces.</p> |
|
</section2> |
|
</section1> |
|
|
|
<section1 topic='Security Considerations' anchor='security'> |
|
<section2 topic='User considerations' anchor='security-user'> |
|
<p>The following are considerations for the user (exemplified by Juliet in this document):</p> |
|
<ul> |
|
<li>A malicious client or other entity with access to the user's account |
|
can perform a migration, potentially against the user's will and/or |
|
without their knowledge. Although this is a concern, any malicious |
|
actor with access to a user's account can abuse that access in many |
|
ways. Servers that support granting restricted access to accounts |
|
should consider blocking attempts to publish to the |
|
'urn:xmpp:moved:1' PEP node from restricted entities.</li> |
|
<li>To avoid leaking the user's new JID to non-contacts, the PEP node |
|
containing the moved statement SHOULD be configured to use the |
|
"presence" access model (this is the default access model defined |
|
by PEP).</li> |
|
</ul> |
|
</section2> |
|
<section2 topic='Contact considerations' anchor='security-contact'> |
|
<p>The following are considerations for the contact (exemplified by Romeo in this document), and the contact's server:</p> |
|
<ul> |
|
<li>A presence subscription with a <moved/> is trivial for a |
|
malicious third-party to spoof. The verification methods discussed |
|
in this document MUST be followed to prevent accepting rogue |
|
subscription requests.</li> |
|
<li>It is important to verify that the original JID of the migrating |
|
user was already authorized to view presence before processing a |
|
migration.</li> |
|
<li>After successfully processing a migration, the original account |
|
should have its presence subscription revoked. This ensures that |
|
each JID may only be migrated once. Without this precaution the |
|
migration mechanism can be abused to introduce unlimited arbitrary |
|
JIDs to contacts' rosters. This precaution also ensures, if the |
|
old account ends up owned by a new entity, that they will not |
|
unexpectedly inherit a presence subscription.</li> |
|
</ul> |
|
</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>This specification defines the following XML namespace:</p> |
|
<ul> |
|
<li>urn:xmpp:moved:1</li> |
|
</ul> |
|
</section1> |
|
|
|
<section1 topic='Design Considerations' anchor='design'> |
|
<section2 topic='Verification methods' anchor='design-verification'> |
|
<p>There are two general approaches for verification - network-based |
|
verification, or cryptographic verification. Network-based verification |
|
(as described in this document) requests a verification statement from |
|
the user's old account. Cryptographic verification would check a move |
|
notification against a previously-established cryptographic identify of |
|
the user.</p> |
|
<p>Network-based verification:</p> |
|
<ul> |
|
<li>Pro: Simple and easy to implement</li> |
|
<li>Con: depends on the original server being available and supporting PEP</li> |
|
</ul> |
|
<p>Cryptographic verification:</p> |
|
<ul> |
|
<li>Pro: Can work even if the original server goes offline or begins blocking |
|
migration attempts.</li> |
|
<li>Con: More complex implementation.</li> |
|
<li>Con: Requires user and contacts to manage/track cryptographic keys and |
|
identies. It may be possible to piggyback on top of an existing cryptographic |
|
layer, e.g. OMEMO. However this would eliminate the server-side assistance, |
|
and OMEMO support is not universal among clients.</li> |
|
</ul> |
|
|
|
<p>Ultimately this document defines a network-based verification method, but |
|
leaves an obvious path to extend the protocol with alternative verification |
|
methods (either in an update to this document, or defined by other |
|
documents).</p> |
|
</section2> |
|
</section1> |
|
|
|
<section1 topic='XML Schema' anchor='schema'> |
|
<p>To be done upon advancement to Draft.</p> |
|
</section1> |
|
|
|
<section1 topic='Acknowledgements' anchor='ack'> |
|
<p>This document was formerly driven by Tory Patnoe with the support and feedback provided by Doug Abbink, Mikhail Belov, Peter Saint-Andre, and Peter Sheu.</p> |
|
<p>It has since been taken over by the current author who thanks Kim Alvefur, Maxime Buquet and Jonas Schäfer for their input and feedback on this specification.</p> |
|
</section1> |
|
</xep>
|
|
|