This JEP describes best practices regarding implementation of invisible presence by means of XMPP privacy lists.
NOTICE: This Informational JEP defines a best practice or protocol profile that has been approved by the Jabber Council and/or the JSF Board of Directors. Implementations are encouraged and the best practice or protocol profile is appropriate for deployment in production systems.
Status: Active
Type: Informational
Number: 0126
Version: 1.0
Last Updated: 2004-03-05
JIG: Standards JIG
Approving Body: Jabber Council
Dependencies: XMPP Core, XMPP IM
Supersedes: None
Superseded By: None
Short Name: N/A
Email: stpeter@jabber.org
JID: stpeter@jabber.org
This Jabber Enhancement Proposal is copyright 1999 - 2005 by the Jabber Software Foundation (JSF) and is in full conformance with the JSF's Intellectual Property Rights Policy <http://www.jabber.org/jsf/ipr-policy.shtml>. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at <http://www.opencontent.org/openpub/>).
The preferred venue for discussion of this document is the Standards-JIG discussion list: <http://mail.jabber.org/mailman/listinfo/standards-jig>.
The Extensible Messaging and Presence Protocol (XMPP) is defined in the XMPP Core (RFC 3920) and XMPP IM (RFC 3921) specifications contributed by the Jabber Software Foundation to the Internet Standards Process, which is managed by the Internet Engineering Task Force in accordance with RFC 2026. Any protocol defined in this JEP has been developed outside the Internet Standards Process and is to be understood as an extension to XMPP rather than as an evolution, development, or modification of XMPP itself.
The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
Several popular instant messaging services implement a feature known as invisibility: the ability to remain online yet appear offline to some or all of one's contacts. A number of Jabber servers and clients have also implemented such a feature, using special values of the <presence/> element's 'type' attribute (e.g., <presence type='invisible'/>). Unfortunately, such implementations are not compliant with XMPP Core [1] and XMPP IM [2], which specify that only the 'type' attribute values defined in the XML schema for the 'jabber:client' and 'jabber:server' namespaces are allowed in XMPP (and those values do not include "invisible"). However, XMPP IM also defines a privacy lists protocol (i.e., the 'jabber:iq:privacy' namespace) that can be used to implement invisibility in an XMPP-compliant manner. This JEP documents how to do just that.
This document addresses the following requirements:
This JEP addresses the following use cases:
These use cases are defined below in "chronological" order by following a scenario in which a user (1) logs in as invisible, (2) becomes selectively visible to certain contacts, (3) becomes visible to all contacts, (4) becomes selectively invisible to certain contacts, and finally (5) becomes invisible to all contacts.
If a user wants to log in as invisible, a certain order of events MUST be followed. Specifically, after authenticating but before sending initial presence, the user MUST define (if necessary) and set as active a privacy list that blocks all outbound presence notifications.
... authentication / session establishment ... <iq from='bilbo@tolkien.lit/shire' type='set' id='inv1'> <query xmlns='jabber:iq:privacy'> <list name='invisible'> <item action='deny' order='1'> <presence-out/> </item> </list> </query> </iq> <iq from='bilbo@tolkien.lit/shire' type='set' id='active1'> <query xmlns='jabber:iq:privacy'> <active name='invisible'/> </query> </iq>
Naturally, the user could have defined this list during a previous session and could simply set the relevant list as active when logging in, rather than defining the list on login. Both steps are shown here for completeness.
The user may now send initial presence to the server.
<presence> <status>I'm not really here, you understand!</status> </presence>
Even though the user has sent initial presence, that presence information will not be broadcasted to any of the user's contacts, since the active privacy list blocks all outbound presence notifications.
Let us now suppose that the user tires of being globally invisible, and decides to become visible to some -- but not all -- contacts (not even famous magic rings possess this feature). The 'jabber:iq:privacy' namespace gives the user three options:
Examples of these options are shown below.
<iq from='bilbo@tolkien.lit/shire' type='set' id='inv2'> <query xmlns='jabber:iq:privacy'> <list name='visible-to-Frodo'> <item type='jid' value='frodo@tolkien.lit' action='allow' order='1'> <presence-out/> </item> <item action='deny' order='2'> <presence-out/> </item> </list> </query> </iq> <iq from='bilbo@tolkien.lit/shire' type='set' id='active2'> <query xmlns='jabber:iq:privacy'> <active name='visible-to-Frodo'/> </query> </iq>
The foregoing privacy list blocks outbound presence notifications to every JID except one. In order to ensure synchronization of presence notifications, the client SHOULD now send the user's last available presence to any active resources associated with the selected JID:
<presence from='bilbo@tolkien.net/shire' to='frodo@tolkien.lit/garden'> <status>I'm not really here, you understand!</status> </presence>
<iq from='bilbo@tolkien.lit/shire' type='set' id='inv3'> <query xmlns='jabber:iq:privacy'> <list name='visible-to-Bagginses'> <item type='group' value='Bagginses' action='allow' order='1'> <presence-out/> </item> <item action='deny' order='2'> <presence-out/> </item> </list> </query> </iq> <iq from='bilbo@tolkien.lit/shire' type='set' id='active3'> <query xmlns='jabber:iq:privacy'> <active name='visible-to-Bagginses'/> </query> </iq>
The foregoing privacy list blocks outbound presence notifications to every JID except those in a certain roster group. In order to ensure synchronization of presence notifications, the client SHOULD now send the user's last available presence to any active resources associated with JIDs in that group:
<presence from='bilbo@tolkien.net/shire' to='frodo@tolkien.lit/garden'> <status>I'm not really here, you understand!</status> </presence> <presence from='bilbo@tolkien.net/shire' to='bungo@tolkien.lit/pub'> <status>I'm not really here, you understand!</status> </presence> <presence from='bilbo@tolkien.net/shire' to='rosa.baggins@tolkien.lit/home'> <status>I'm not really here, you understand!</status> </presence>
Becoming visible or invisible by subscription type is probably much less likely than becoming visible by JID or roster group; however, it is described here for the sake of completeness.
<iq from='bilbo@tolkien.lit/shire' type='set' id='inv4'> <query xmlns='jabber:iq:privacy'> <list name='visible-to-both'> <item type='subscription' value='both' action='allow' order='1'> <presence-out/> </item> <item action='deny' order='2'> <presence-out/> </item> </list> </query> </iq> <iq from='bilbo@tolkien.lit/shire' type='set' id='active4'> <query xmlns='jabber:iq:privacy'> <active name='visible-to-both'/> </query> </iq>
The foregoing privacy list blocks outbound presence notifications to every JID except those that are in the user's roster with a subscription type of "both". Outbound presence notifications are sent accordingly.
Let us now suppose that the user wants to become visible to all those who are subscribed to his presence. This easy to do by defining and setting as active a new privacy list (here again, the privacy list may have been defined previously).
<iq from='bilbo@tolkien.lit/shire' type='set' id='inv5'> <query xmlns='jabber:iq:privacy'> <list name='visible'> <item action='allow' order='1'> <presence-out/> </item> </list> </query> </iq> <iq from='bilbo@tolkien.lit/shire' type='set' id='active5'> <query xmlns='jabber:iq:privacy'> <active name='visible'/> </query> </iq>
Because globally allowing outbound presence notifications is most likely the default behavior of any server, a more straightforward way to become globally visible is to decline the use of any active rule (the equivalent, as it were, of taking off a magic invisibility ring):
<iq from='bilbo@tolkien.lit/shire' type='set' id='active6'> <query xmlns='jabber:iq:privacy'> <active/> </query> </iq>
Let us now suppose that the user no longer wants to be globally visible, but desires to be invisible only to some -- but not all -- contacts. As with visibility, here again the 'jabber:iq:privacy' namespace gives the user three options:
Examples of these options are shown below.
<iq from='bilbo@tolkien.lit/shire' type='set' id='inv6'> <query xmlns='jabber:iq:privacy'> <list name='invisible-to-Gandalf'> <item type='jid' value='gandalf@tolkien.lit' action='deny' order='1'> <presence-out/> </item> <item action='allow' order='2'> <presence-out/> </item> </list> </query> </iq> <iq from='bilbo@tolkien.lit/shire' type='set' id='active7'> <query xmlns='jabber:iq:privacy'> <active name='invisible-to-Gandalf'/> </query> </iq>
The foregoing privacy list allows outbound presence notifications to every JID except one. In order to ensure synchronization of presence notifications, the client SHOULD now send unavailable presence from the user to any active resources associated with the selected JID:
<presence from='bilbo@tolkien.net/shire' to='gandalf@tolkien.lit/forest' type='unavailable'/>
<iq from='bilbo@tolkien.lit/shire' type='set' id='inv7'> <query xmlns='jabber:iq:privacy'> <list name='invisible-to-Wizards'> <item type='group' value='Wizards' action='deny' order='1'> <presence-out/> </item> <item action='allow' order='2'> <presence-out/> </item> </list> </query> </iq> <iq from='bilbo@tolkien.lit/shire' type='set' id='active8'> <query xmlns='jabber:iq:privacy'> <active name='invisible-to-Wizards'/> </query> </iq>
The foregoing privacy list allows outbound presence notifications to every JID except those in a certain roster group. In order to ensure synchronization of presence notifications, the client SHOULD now send unavailable presence from the user to any active resources associated with JIDs in that group:
<presence from='bilbo@tolkien.net/shire' to='gandalf@tolkien.lit/forest' type='unavailable'/> <presence from='bilbo@tolkien.net/shire' to='sauramon@tolkien.lit/chamber' type='unavailable'/>
Becoming visible or invisible by subscription type is probably much less likely than becoming visible by JID or roster group; however, it is described here for the sake of completeness.
<iq from='bilbo@tolkien.lit/shire' type='set' id='inv8'> <query xmlns='jabber:iq:privacy'> <list name='invisible-to-from'> <item type='subscription' value='from' action='deny' order='1'> <presence-out/> </item> <item action='allow' order='2'> <presence-out/> </item> </list> </query> </iq> <iq from='bilbo@tolkien.lit/shire' type='set' id='active9'> <query xmlns='jabber:iq:privacy'> <active name='invisible-to-from'/> </query> </iq>
The foregoing privacy list allows outbound presence notifications to every JID except those that are in the user's roster with a subscription type of "to". Outbound presence stanzas of type "unavailable" are sent accordingly.
In order to become globally invisible again, the user simply sets as active the global invisibility list previously defined:
<iq from='bilbo@tolkien.lit/shire' type='set' id='active10'> <query xmlns='jabber:iq:privacy'> <active name='invisible'/> </query> </iq>
The foregoing text explains the protocol used to implement invisibility. Naturally, client developers will most likely want to hide these protocol details from the end user. For example, rather than forcing the end user to navigate the details of privacy list management, a client could simply provide a "Go Invisible" button that sets as active the appropriate privacy list.
Note well that the privacy lists used to implement invisibility SHOULD be active lists and not the default list.
To help ensure cross-client compatibility, it is RECOMMENDED to use the privacy list names "visible" and "invisible" for simple global visibility and invisibility respectively. It is also RECOMMENDED to use list names of the form "visible-to-GroupName" and "invisible-to-JID" for simple lists that implement visibility or invisibility with regard to roster groups and JIDs. Obviously list names could become rather complex, such as "visible-to-Group1 Group2 Group3". Implementations MUST NOT attempt to derive semantic meaning from privacy list names; these recommendations are provided for ease of use only with regard to basic privacy lists related to visibility/invisibility.
In general it is probably easiest for users to become visible/invisible either globally or based on roster group, since these models are conceptually simple. Although, naturally, a client developer cannot tell users what to do, it probably best to encourage the use of conceptually simple models for privacy lists.
Privacy lists can become complex and must be carefully managed by clients. For example, let us imagine that the user is currently applying another active list unrelated to visibility (e.g., a list that blocks communications with a stalker); if the user then clicks "Go Invisible" and the client is not smart, it could overwrite the stalker blocking. Therefore, if the user has an active list that incorporates rules other than those related to visibility/invisibility, the client SHOULD either assume that visibility/invisibility is an overlay on the list currently in use (generating an appropriate privacy list that takes both into account) or prompt the user regarding their intentions. In the absence of privacy lists unrelated to visibility/invisibility, the client may proceed in a less cautious fashion.
For security concerns related to privacy lists, refer to XMPP IM. Care must be taken regarding privacy lists, especially so that visibility/invisibility rules do not overwrite existing rules the user has set for the sake of security and privacy; see the "Implementation Notes" for details.
It is important to recognize that invisibility can be defeated without more advanced privacy lists than those defined above and an awareness of context on the part of a client. For example, a contact can send an IQ request to a user's usual full JID using Last Activity [3], Entity Time [4], or Software Version [5] and receive a reply, thus providing information that reveals the user's availability. In addition, Last Activity requests to the user's bare JID will normally reveal the user's availability as well. To help ensure that the user's invisibility cannot be defeated in this way, the user's client SHOULD add IQ blocking to the relevant privacy list. Finally, the user's client SHOULD NOT return "is-composing" events as defined in Message Events [6] or Chat State Notifications [7].
This JEP requires no interaction with the Internet Assigned Numbers Authority (IANA) [8].
No namespaces or parameters need to be registered with the Jabber Registrar [9] as a result of this JEP.
The XML schema for the 'jabber:iq:privacy' namespace is contained in XMPP IM.
1. RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core <http://www.ietf.org/rfc/rfc3920.txt>.
2. RFC 3921: Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence <http://www.ietf.org/rfc/rfc3921.txt>.
3. JEP-0012: Last Activity <http://www.jabber.org/jeps/jep-0012.html>.
4. JEP-0090: Entity Time <http://www.jabber.org/jeps/jep-0090.html>.
5. JEP-0092: Software Version <http://www.jabber.org/jeps/jep-0092.html>.
6. JEP-0022: Message Events <http://www.jabber.org/jeps/jep-0022.html>.
7. JEP-0085: Chat State Notifications <http://www.jabber.org/jeps/jep-0085.html>.
8. The Internet Assigned Numbers Authority (IANA) is the central coordinator for the assignment of unique parameter values for Internet protocols, such as port numbers and URI schemes. For further information, see <http://www.iana.org/>.
9. The Jabber Registrar maintains a list of reserved Jabber protocol namespaces as well as registries of parameters used in the context of protocols approved by the Jabber Software Foundation. For further information, see <http://www.jabber.org/registrar/>.
END