├── .gitignore ├── .nojekyll ├── CONTRIBUTING.md ├── Intro.md ├── LICENSES ├── CC-BY-4.0.txt ├── CC0-1.0.txt └── Unlicense.txt ├── Readme.md ├── docs ├── Alias │ ├── Alias consumption.md │ ├── Alias database.md │ ├── Alias string.md │ ├── Readme.md │ ├── Registration.md │ ├── Revocation.md │ └── Web endpoint.md ├── Appendix │ ├── Readme.md │ ├── muxrpc.md │ └── ssb-uris.md ├── Misc │ ├── External resolution.md │ ├── muxrpc alias registration.md │ └── sequenceDiagram example.md ├── Participation │ ├── Attendants.md │ ├── Internal user authentication.md │ ├── Internal user registry.md │ ├── Invites.md │ ├── Joining.md │ ├── Metadata.md │ ├── Readme.md │ ├── Tunnel addresses.md │ ├── Tunneled authentication.md │ └── Tunneled connection.md ├── Setup │ ├── Components.md │ ├── Config database.md │ ├── Privacy modes.md │ ├── Readme.md │ └── Web Dashboard.md └── Stakeholders │ ├── External user.md │ ├── Internal user.md │ ├── Moderator.md │ ├── Readme.md │ └── Room admin.md └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Andre 'Staltz' Medeiros 2 | # 3 | # SPDX-License-Identifier: Unlicense 4 | 5 | .obsidian 6 | node_modules 7 | pnpm-lock.yaml 8 | tools/compiled.md 9 | tools/*.md -------------------------------------------------------------------------------- /.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssbc/rooms2/4e9537b6b423c2437ca2c96516ce594b15e6db88/.nojekyll -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | To produce the HTML, run `npx stuffem Readme.md`. 8 | -------------------------------------------------------------------------------- /Intro.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # SSB Rooms 2.0 8 | 9 | **Revision:** `$REVISION` 10 | 11 | **Author:** Andre Medeiros 12 | 13 | **License:** This work is licensed under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/). 14 | 15 | ## Abstract 16 | 17 | A room server is an SSB peer with privileged internet presence (for instance, not behind a NAT layer) which allows its clients to perform tunneled connections wich each other. For practical purposes, room clients seem to be connected to each other directly, but the room is an intermediary. Connections between server and client are end-to-end encrypted via secret-handshake, as well as in tunneled connections between room clients, so that the room server cannot eavesdrop on the payloads in the tunneled connections. This document describes new capabilities for rooms, such as user aliases, privacy modes, and tunneled authentication. 18 | 19 | ## Terminology 20 | 21 | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119). 22 | 23 | ## Table of contents 24 | -------------------------------------------------------------------------------- /LICENSES/CC-BY-4.0.txt: -------------------------------------------------------------------------------- 1 | Creative Commons Attribution 4.0 International 2 | 3 | Creative Commons Corporation (“Creative Commons”) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is” basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. 4 | 5 | Using Creative Commons Public Licenses 6 | 7 | Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. 8 | 9 | Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. More considerations for licensors. 10 | 11 | Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor’s permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More considerations for the public. 12 | 13 | Creative Commons Attribution 4.0 International Public License 14 | 15 | By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. 16 | 17 | Section 1 – Definitions. 18 | 19 | a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. 20 | 21 | b. Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. 22 | 23 | c. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. 24 | 25 | d. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. 26 | 27 | e. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. 28 | 29 | f. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. 30 | 31 | g. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. 32 | 33 | h. Licensor means the individual(s) or entity(ies) granting rights under this Public License. 34 | 35 | i. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. 36 | 37 | j. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. 38 | 39 | k. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. 40 | 41 | Section 2 – Scope. 42 | 43 | a. License grant. 44 | 45 | 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: 46 | 47 | A. reproduce and Share the Licensed Material, in whole or in part; and 48 | 49 | B. produce, reproduce, and Share Adapted Material. 50 | 51 | 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 52 | 53 | 3. Term. The term of this Public License is specified in Section 6(a). 54 | 55 | 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. 56 | 57 | 5. Downstream recipients. 58 | 59 | A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. 60 | 61 | B. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 62 | 63 | 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). 64 | 65 | b. Other rights. 66 | 67 | 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 68 | 69 | 2. Patent and trademark rights are not licensed under this Public License. 70 | 71 | 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. 72 | 73 | Section 3 – License Conditions. 74 | 75 | Your exercise of the Licensed Rights is expressly made subject to the following conditions. 76 | 77 | a. Attribution. 78 | 79 | 1. If You Share the Licensed Material (including in modified form), You must: 80 | 81 | A. retain the following if it is supplied by the Licensor with the Licensed Material: 82 | 83 | i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); 84 | 85 | ii. a copyright notice; 86 | 87 | iii. a notice that refers to this Public License; 88 | 89 | iv. a notice that refers to the disclaimer of warranties; 90 | 91 | v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; 92 | 93 | B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and 94 | 95 | C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. 96 | 97 | 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 98 | 99 | 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. 100 | 101 | 4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. 102 | 103 | Section 4 – Sui Generis Database Rights. 104 | 105 | Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: 106 | 107 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; 108 | 109 | b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and 110 | 111 | c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. 112 | For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. 113 | 114 | Section 5 – Disclaimer of Warranties and Limitation of Liability. 115 | 116 | a. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. 117 | 118 | b. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. 119 | 120 | c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. 121 | 122 | Section 6 – Term and Termination. 123 | 124 | a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. 125 | 126 | b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 127 | 128 | 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 129 | 130 | 2. upon express reinstatement by the Licensor. 131 | 132 | c. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. 133 | 134 | d. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. 135 | 136 | e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. 137 | 138 | Section 7 – Other Terms and Conditions. 139 | 140 | a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. 141 | 142 | b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. 143 | 144 | Section 8 – Interpretation. 145 | 146 | a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. 147 | 148 | b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. 149 | 150 | c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. 151 | 152 | d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. 153 | 154 | Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. 155 | 156 | Creative Commons may be contacted at creativecommons.org. 157 | -------------------------------------------------------------------------------- /LICENSES/CC0-1.0.txt: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /LICENSES/Unlicense.txt: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. 4 | 5 | In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and 6 | successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | 10 | For more information, please refer to 11 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | - [Intro](Intro.md) 8 | - [Stakeholders](docs/Stakeholders/Readme.md) 9 | - [Administrator](docs/Stakeholders/Room%20admin.md) 10 | - [Internal user](docs/Stakeholders/Internal%20user.md) 11 | - [External user](docs/Stakeholders/External%20user.md) 12 | - [Moderator](docs/Stakeholders/Moderator.md) 13 | - [Setup](docs/Setup/Readme.md) 14 | - [Components](docs/Setup/Components.md) 15 | - [Privacy modes](docs/Setup/Privacy%20modes.md) 16 | - [Config database](docs/Setup/Config%20database.md) 17 | - [Web Dashboard](docs/Setup/Web%20Dashboard.md) 18 | - [Participation](docs/Participation/Readme.md) 19 | - [Joining](docs/Participation/Joining.md) 20 | - [Internal user registry](docs/Participation/Internal%20user%20registry.md) 21 | - [Internal user authentication](docs/Participation/Internal%20user%20authentication.md) 22 | - [Invites](docs/Participation/Invites.md) 23 | - [Tunnel addresses](docs/Participation/Tunnel%20addresses.md) 24 | - [Tunneled connection](docs/Participation/Tunneled%20connection.md) 25 | - [Tunneled authentication](docs/Participation/Tunneled%20authentication.md) 26 | - [Metadata API](docs/Participation/Metadata.md) 27 | - [Attendants API](docs/Participation/Attendants.md) 28 | - [User aliases](docs/Alias/Readme.md) 29 | - [Alias string](docs/Alias/Alias%20string.md) 30 | - [Registration](docs/Alias/Registration.md) 31 | - [Revocation](docs/Alias/Revocation.md) 32 | - [Alias consumption](docs/Alias/Alias%20consumption.md) 33 | - [Alias web endpoint](docs/Alias/Web%20endpoint.md) 34 | - [Alias database](docs/Alias/Alias%20database.md) 35 | - [Appendix](docs/Appendix/Readme.md) 36 | - [List of new muxrpc APIs](docs/Appendix/muxrpc.md) 37 | - [List of new SSB URIs](docs/Appendix/ssb-uris.md) 38 | -------------------------------------------------------------------------------- /docs/Alias/Alias consumption.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Alias consumption 8 | 9 | When an SSB user ([external](../Stakeholders/External%20user.md) or [internal](../Stakeholders/Internal%20user.md)) is connected to the room, and knows of another [internal user's](../Stakeholders/Internal%20user.md) [alias](Alias%20string.md), they can perform *alias consumption*. After consumption is completed successfully, they authentically obtain the target user's SSB ID and can use it to start a [tunneled connection](../Participation/Tunneled%20connection.md). 10 | 11 | ### Specification 12 | 13 | The input for the consumption algorithm is the response from the [web endpoint](Web%20endpoint.md), which is (either through JSON or SSB URI): the room's multiserver `address`, `roomId`, `userId`, `alias`, and `signature`. 14 | 15 | 1. The SSB user verifies that the `signature` authentically matches `roomId`, `userId` and `alias` 16 | 1. If it is an invalid signature, interrupt alias consumption with a failure indicating that the alias association to the internal user `userId` was probably forged 17 | 1. Else, proceed (below) 18 | 1. The SSB user acting as a client connects to the room's `address` and establishes a [muxrpc](https://github.com/ssb-js/muxrpc/) connection 19 | 1. The client can now use `userId` to initiate a [tunneled connection](../Participation/Tunneled%20connection.md) with them 20 | 1. (Optional and recommended) The client *follows* the `userId`, see [tunneled authentication](../Participation/Tunneled%20authentication.md) 21 | -------------------------------------------------------------------------------- /docs/Alias/Alias database.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Alias database 8 | 9 | This is a database that stores all aliases that were [registered](Registration.md) by internal users. 10 | 11 | ### Example 12 | 13 | The following is a mock up of a key-value store: 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
KeyValue
alice@FlieaFef19uJ6jhHwv2CSkFrDLYKJd/SuIS71A5Y2as=.ed25519 plus signature
bob@25WfId3Vx/gyMAZqCyZzhtW4iPtUVXB/aOMYbq44P4c=.ed25519 plus signature
carla@dRE+jzKo0VWX6JbcSVATyOvFlbjCNwPWNzQLkTGenac=.ed25519 plus signature
daniel@SMMgb4bZAgRgtAPdMw4loQeZL9lQgsRDi+xin0ZDzAg=.ed25519 plus signature
39 | 40 | ### Specification 41 | 42 | This can be a simple persistent key-value store, such as Leveldb. 43 | 44 | - Each **Key** is an [alias string](Alias%20string.md) 45 | - Each **Value** is a string that encodes two things: 46 | - [SSB identity](https://ssbc.github.io/scuttlebutt-protocol-guide/#keys-and-identities) of the [internal user](../Stakeholders/Internal%20user.md) 47 | - A cryptographic signature that covers **all these** 48 | - the room server's ID, i.e. `roomId` 49 | - the SSB ID, i.e. `userId` 50 | - alias string, i.e. `alias` 51 | 52 | The signature is applied on the following string: `=room-alias-registration:${roomId}:${userId}:${alias}`, known as the *Alias confirmation*, see example (without spaces nor newlines): 53 | 54 | ``` 55 | =room-alias-registration:@51w4nYL0k7mRzDGw20KQqCjt35 56 | y8qLiBNtWk3MX7ppo=.ed25519:@FlieaFef19uJ6jhHwv2 57 | CSkFrDLYKJd/SuIS71A5Y2as=.ed25519:alice 58 | ``` 59 | 60 | where 61 | 62 | - `roomId` is `@51w4nYL0k7mRzDGw20KQqCjt35y8qLiBNtWk3MX7ppo=.ed25519` 63 | - `userId` is `@FlieaFef19uJ6jhHwv2CSkFrDLYKJd/SuIS71A5Y2as=.ed25519` 64 | - `alias` is `alice` 65 | 66 | The purpose of a cryptographic signature on the combined `roomId` & `userId` & `alias` is to make sure that the [Room admin](../Stakeholders/Room%20admin.md) cannot tamper with the database to delegitimize its contents. This means that each key-value pair is certainly authored by the declared SSB ID, that is, neither the key (the alias) nor the value (the SSB ID) was modified by the Room admin. 67 | 68 | ### Security considerations 69 | 70 | #### Malicious [room admin](../Stakeholders/Room%20admin.md) 71 | 72 | The room admin can freely read or write to this database, they can create new entries, and so forth. If they modify an entry and thus break the validation of the signatures, other SSB users can detect this when verifying the signatures. 73 | 74 | Thus the admin **cannot** effectively: 75 | 76 | - Register a signed alias on behalf of an [internal user](../Stakeholders/Internal%20user.md) 77 | - Modify a registered alias made by [internal users](../Stakeholders/Internal%20user.md) 78 | 79 | But the admin **can**: 80 | 81 | - Remove any registered key-value pairs from the database, essentially removing an alias 82 | - Register signed aliases for fake users it has created itself 83 | 84 | #### Malicious [moderator](../Stakeholders/Moderator.md) 85 | 86 | Similar considerations as with the room admin, but less powers. The malicious moderator *cannot* do the actions that the room admin cannot do (otherwise moderators would have more power than admins), but the one thing moderators can do is: 87 | 88 | - Remove any registered key-value pairs from the database, essentially removing an alias 89 | -------------------------------------------------------------------------------- /docs/Alias/Alias string.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Alias string 8 | 9 | An [internal user](../Stakeholders/Internal%20user.md)'s alias, also known as "alias string", is used to uniquely (unique within the room server only) identify that internal user. This string is useful only within the context of the room, i.e. not globally identifiable. 10 | 11 | ### Example 12 | 13 | Suppose Alice is an internal user of the room "Scuttlebutt EU". Alice's alias could be one of these strings (non-exhaustive list): 14 | 15 | - `alice` 16 | - `alice1994` 17 | - `alice94` 18 | 19 | ### Specification 20 | 21 | The string should satisfy the same rules as domain "labels" as defined in [RFC 1035](https://tools.ietf.org/html/rfc1035). 22 | -------------------------------------------------------------------------------- /docs/Alias/Readme.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Alias 8 | 9 | An alias (also known as "room alias") is a string that identifies an [internal user](../Stakeholders/Internal%20user.md), designed to be short and human-friendly, similar to [email addresses](https://en.wikipedia.org/wiki/Email_address) and [Mastodon WebFinger addresses](https://docs.joinmastodon.org/spec/webfinger/). The purpose of aliases is to improve the user experience of accurately (1) **identifying** the internal user and (2) **locating** the internal user at a room server for the purpose of establishing a connection with them. 10 | 11 | As an example, suppose Alice is an internal user of the room "Scuttlebutt EU". The room's domain is `scuttlebutt.eu` and Alice's [alias](Alias%20string.md) is `alice`. Alice's [alias endpoint](Web%20endpoint.md) is thus `alice.scuttlebutt.eu`. 12 | 13 | In short, 14 | 15 | - Anyone can access an alias [web endpoint](Web%20endpoint.md) 16 | - [Internal users](../Stakeholders/Internal%20user.md) can [register](Registration.md) and [revoke](Revocation.md) their aliases 17 | - [Internal users](../Stakeholders/Internal%20user.md) and [external users](../Stakeholders/External%20user.md) who visit a target user's [alias endpoint](Web%20endpoint.md) can [consume it](Alias%20consumption.md) in order to [connect](../Participation/Tunneled%20connection.md) with the target internal user 18 | - [Room admins](../Stakeholders/Room%20admin.md) have read/write access to the [alias database](Alias%20database.md) but can't add cryptographically valid entries since they are signed by the owner 19 | - [Moderators](../Stakeholders/Moderator.md) can remove alias entries from the [alias database](Alias%20database.md) 20 | -------------------------------------------------------------------------------- /docs/Alias/Registration.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Alias registration 8 | 9 | An [internal user](../Stakeholders/Internal%20user.md) who does not have an alias in the current room server can choose to register an alias. Not all internal users need to have aliases, so the process described here is optional. 10 | 11 | ### Specification 12 | 13 | 1. An internal user with SSB ID `feedId` and a room server with SSB ID `roomId` are connected to each other via secret-handshake 14 | 1. The internal user chooses a `alias` as a candidate [alias string](Alias%20string.md) 15 | 1. The internal user calls a specific [muxrpc](https://github.com/ssb-js/muxrpc/) `async` API `room.registerAlias(alias, signature)` where `signature` is a cryptographic signature of the string `=room-alias-registration:${roomId}:${feedId}:${alias}` using `feedId`'s cryptographic keypair, read more about it in the [alias database](Alias%20database.md) spec 16 | 1. The room, upon receiving the `room.registerAlias` muxrpc call, checks whether that `alias` is valid (see spec in [Alias string](Alias%20string.md)) 17 | 1. If it is invalid, respond `room.registerAlias` with an error 18 | 1. Else, proceed (below) 19 | 1. The room checks whether there already exists an entry in the [Alias database](Alias%20database.md) with the *key* `alias` 20 | 1. If there is, respond `room.registerAlias` with an error 21 | 1. Else, proceed (below) 22 | 1. The room adds an entry to its [Alias database](Alias%20database.md) for `key=alias` & `value=feedId+sig` 23 | 1. The room responds `room.registerAlias` with a string containing the [Alias endpoint URL](Web%20endpoint.md) for the newly registered alias, indicating success 24 | 1. The internal user receives the room's response to `room.registerAlias` 25 | 1. If it is an error, then (optionally) display a user interface failure to register the alias 26 | 1. If it is a successful `url` string, then the internal user **MAY** publish an SSB msg of type `about` with a field listing all its aliases for various rooms, where this specific `url` is included. The specific schema of the message type is an application-level concern 27 | 28 | The above algorithm is also provided below as a UML sequence diagram: 29 | 30 | ```mermaid 31 | sequenceDiagram 32 | participant U as SSB peer 33 | participant R as Room server 34 | 35 | U->>R: (muxrpc async) `room.registerAlias(alias, signature)` 36 | alt `alias` is an invalid alias string
or already taken in the alias database
or other errors 37 | R-->>U: Respond room.registerAlias with an error 38 | opt 39 | U->>U: Display user interface error 40 | end 41 | else else 42 | R->>R: Adds an entry to
its alias database 43 | R-->>U: Respond `room.registerAlias` with a `url` string 44 | U->>U: Publishes an SSB
msg of type
`about` 45 | end 46 | ``` 47 | 48 | ### Security considerations 49 | 50 | #### Malicious [internal user](../Stakeholders/Internal%20user.md) 51 | 52 | A malicious internal user could take many or all possible aliases in case the room accidentally allows such malicious user to become an internal user. Arguably, some room implementations could choose to allow only one alias per internal user, and that would still be compliant with this spec. 53 | 54 | ### Malicious [room admin](../Stakeholders/Room%20admin.md) 55 | 56 | The room admin could reply with errors when technically the muxrpc should have succeeded, e.g. pretending that the `alias` candidate is invalid or pretending that it's already registered. -------------------------------------------------------------------------------- /docs/Alias/Revocation.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Alias revocation 8 | 9 | When an [internal user](../Stakeholders/Internal%20user.md) who has [registered](Registration.md) no longer wishes to have that alias associated with them anymore, they can perform *alias revocation* to remove that alias from the [alias database](Alias%20database.md). 10 | 11 | ### Specification 12 | 13 | 1. An internal user with SSB ID `feedId` and a room server with SSB ID `roomId` are connected to each other via secret-handshake 14 | 1. The internal user calls a specific [muxrpc](https://github.com/ssb-js/muxrpc/) `async` API `room.revokeAlias(alias, callback)` 15 | 1. The room, upon receiving the `room.revokeAlias` muxrpc call, checks whether there exists an entry in the [Alias database](Alias%20database.md) for `alias` 16 | 1. If there is no entry, respond `room.revokeAlias` with an error 17 | 1. Else, if there exists an entry for `alias` but it is not owned by `feedId`, respond `room.revokeAlias` with an error 18 | 1. Else, proceed (below) 19 | 1. The room removes the entry from the [Alias database](Alias%20database.md) associated with `feedId` 20 | 1. The room responds `room.revokeAlias` with `true`, indicating success 21 | 1. The internal user receives the room's response to `room.revokeAlias` 22 | 1. If it is an error, then (optionally) display a user interface failure to revoke the alias 23 | 1. If it is `true`, then publish an SSB msg of type `about` with a field listing all its aliases for various rooms, where this specific `alias` is no longer listed. The specific schema of the message type is an application-level concern 24 | 25 | The above algorithm is also provided below as a UML sequence diagram: 26 | 27 | ```mermaid 28 | sequenceDiagram 29 | participant U as SSB peer 30 | participant R as Room server 31 | 32 | U->>R: (muxrpc async) `room.revokeAlias(alias)` 33 | alt `alias` does not exist, or other errors 34 | R-->>U: Respond room.revokeAlias with an error 35 | opt 36 | U->>U: Display user interface error 37 | end 38 | else else 39 | R->>R: Remove the entry in
the alias database 40 | R-->>U: Respond room.revokeAlias with `true` 41 | U->>U: Publishes an SSB
msg of type
`about` 42 | end 43 | ``` 44 | 45 | ### Security considerations 46 | 47 | #### Malicious [room admin](../Stakeholders/Room%20admin.md) 48 | 49 | The room admin could refuse to remove the database entry, or could delete the database entry at will (before the internal user performs revocation). In other words, the internal user does not ultimately have power over the deletion of the alias entry from the alias database, it must trust the room admin regarding deletion. -------------------------------------------------------------------------------- /docs/Alias/Web endpoint.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Web endpoint 8 | 9 | Once an alias is [registered](Registration.md), it enables any web user to visit a web endpoint on the room server dedicated to that alias, for the purpose of telling the visitor what SSB ID does the alias resolve to, and with instructions on how to install an SSB app if the visitor doesn't have it yet. 10 | 11 | The goal of this endpoint is to help any SSB user *locate and identify* the alias' owner by resolving the alias to: (1) the room's [multiserver address](https://github.com/ssb-js/multiserver), (2) the owner's SSB ID, and (3) a cryptographic signature that proves the owner associated themselves with that alias. This web endpoint is valuable to onboard new SSB users being invited by an [internal user](../Stakeholders/Internal%20user.md). 12 | 13 | **Prior art:** This endpoint should be in many ways similar to the [Telegram](https://telegram.org/) `https://t.me/example` service for the username `@example`, also capable of redirecting the web visitor to a scheme `tg` URI `tg://resolve?domain=example`, which Telegram apps know how to parse and open the target user's profile screen. 14 | 15 | ### Specification 16 | 17 | This specification does not apply if the [privacy mode](../Setup/Privacy%20modes.md) is *Restricted*. This web endpoint is available only if the privacy mode is *Open* or *Community*. 18 | 19 | If the alias `${alias}` is registered at the room `${roomHost}` for a certain `${userId}`, then the room's HTTP endpoint reserved for the alias **SHOULD** be the wildcard subdomain URL `https://${alias}.${roomHost}` but it **MAY** be `https://${roomHost}/${alias}`. 20 | 21 | The HTML response then: 22 | 23 | - **MAY** inform users how to install an SSB app that can correctly consume room aliases 24 | - **SHOULD** render a "Connect with me" button linking to an SSB URI (see below) 25 | - The page **MAY** automatically redirect (when the browser supports it) to an SSB URI (see below) 26 | - The alias SSB URI **MUST** be `ssb:experimental?action=consume-alias&alias=${alias}&userId=${userId}&signature=${signature}&roomId=${roomId}&multiserverAddress=${roomMsAddr}`, in other words there are 6 query components: 27 | - `action=consume-alias`, a constant string to identify the purpose of this URI 28 | - `alias=${alias}`, the [alias string](Alias%20string.md) 29 | - `userId=${userId}`, the SSB ID of the alias's owner 30 | - `roomId=${roomId}`, the room's SSB ID 31 | - `signature=${signature}`, the alias's owner signature as described in the [alias database](Alias%20database.md) 32 | - `multiserverAddress=${roomMsAddr}`, the room's [multiserver address](https://github.com/ssb-js/multiserver) using percent encoding for URIs 33 | 34 | As an additional endpoint for programmatic purposes, if the query parameter `encoding=json` is added to the alias endpoint (for illustration: `https://${alias}.${roomHost}?encoding=json`), then, in successful responses, the JSON body **MUST** conform to the following schema: 35 | 36 | ```json 37 | { 38 | "$schema": "http://json-schema.org/draft-07/schema#", 39 | "$id": "https://github.com/ssb-ngi-pointer/rooms2#alias-json-endpoint-success", 40 | "type": "object", 41 | "properties": { 42 | "status": { 43 | "title": "Response status tag", 44 | "description": "Indicates the completion status of this response", 45 | "type": "string", 46 | "pattern": "^(successful)$" 47 | }, 48 | "multiserverAddress": { 49 | "title": "Multiserver address", 50 | "description": "Should conform to https://github.com/ssbc/multiserver-address", 51 | "type": "string" 52 | }, 53 | "roomId": { 54 | "title": "Room ID", 55 | "description": "SSB ID for the room server", 56 | "type": "string" 57 | }, 58 | "userId": { 59 | "title": "User ID", 60 | "description": "SSB ID for the user owning the alias", 61 | "type": "string" 62 | }, 63 | "alias": { 64 | "title": "Alias", 65 | "description": "A domain 'label' as defined in RFC 1035", 66 | "type": "string" 67 | }, 68 | "signature": { 69 | "title": "Signature", 70 | "description": "Cryptographic signature covering the roomId, the userId, and the alias", 71 | "type": "string" 72 | } 73 | }, 74 | "required": [ 75 | "status", 76 | "multiserverAddress", 77 | "roomId", 78 | "userId", 79 | "alias", 80 | "signature" 81 | ] 82 | } 83 | ``` 84 | 85 | In failed responses, the JSON body **MUST** conform to the following schema: 86 | 87 | ```json 88 | { 89 | "$schema": "http://json-schema.org/draft-07/schema#", 90 | "$id": "https://github.com/ssb-ngi-pointer/rooms2#alias-json-endpoint-error", 91 | "type": "object", 92 | "properties": { 93 | "status": { 94 | "title": "Response status tag", 95 | "description": "Indicates the completion status of this response", 96 | "type": "string" 97 | }, 98 | "error": { 99 | "title": "Response error", 100 | "description": "Describes the specific error that occurred", 101 | "type": "string" 102 | } 103 | }, 104 | "required": [ 105 | "status", 106 | "error" 107 | ] 108 | } 109 | ``` 110 | 111 | ### Example 112 | 113 | Suppose the alias is `bob`, registered for the user ID `@yVQxFxzeRQ13DQ813hf8G20U5z5I/nkNDliKeSs/IpU=.ed25519` at the room with host name `scuttlebutt.eu`. Then the alias endpoint `https://bob.scuttlebutt.eu` responds with HTML containing the following SSB URI: 114 | 115 | [ssb:experimental?action=consume-alias&multiserverAddress=net%3Ascuttlebutt.eu%3A8008~shs%3Azz%2Bn7zuFc4wofIgKeEpXgB%2B%2FXQZB43Xj2rrWyD0QM2M%3D&alias=bob&roomId=%40zz%2Bn7zuFc4wofIgKeEpXgB%2B%2FXQZB43Xj2rrWyD0QM2M%3D.ed25519&userId=%40yVQxFxzeRQ13DQ813hf8G20U5z5I%2FnkNDliKeSs%2FIpU%3D.ed25519&signature=EiEgn%2Fh2lKoaz28ggKBod6havJNKapRKCmXQ%2Ft%2F4KS1gY4T6zPXWhw6kTaglt8vDJZW%2BjJRJvfB4Rryhl0njCg%3D%3D.sig.ed25519](ssb:experimental?action=consume-alias&multiserverAddress=net%3Ascuttlebutt.eu%3A8008~shs%3Azz%2Bn7zuFc4wofIgKeEpXgB%2B%2FXQZB43Xj2rrWyD0QM2M%3D&alias=bob&roomId=%40zz%2Bn7zuFc4wofIgKeEpXgB%2B%2FXQZB43Xj2rrWyD0QM2M%3D.ed25519&userId=%40yVQxFxzeRQ13DQ813hf8G20U5z5I%2FnkNDliKeSs%2FIpU%3D.ed25519&signature=EiEgn%2Fh2lKoaz28ggKBod6havJNKapRKCmXQ%2Ft%2F4KS1gY4T6zPXWhw6kTaglt8vDJZW%2BjJRJvfB4Rryhl0njCg%3D%3D.sig.ed25519) 116 | 117 | The JSON endpoint `https://bob.scuttlebutt.eu/?encoding=json` would respond with the following JSON: 118 | 119 | ```json 120 | { 121 | "status": "successful", 122 | "multiserverAddress": "net:scuttlebutt.eu:8008~shs:zz+n7zuFc4wofIgKeEpXgB+/XQZB43Xj2rrWyD0QM2M=", 123 | "roomId": "@zz+n7zuFc4wofIgKeEpXgB+/XQZB43Xj2rrWyD0QM2M=.ed25519", 124 | "userId": "@yVQxFxzeRQ13DQ813hf8G20U5z5I/nkNDliKeSs/IpU=.ed25519", 125 | "alias": "bob", 126 | "signature": "EiEgn/h2lKoaz28ggKBod6havJNKapRKCmXQ/t/4KS1gY4T6zPXWhw6kTaglt8vDJZW+jJRJvfB4Rryhl0njCg==.sig.ed25519" 127 | } 128 | ``` 129 | 130 | ### Security considerations 131 | 132 | #### Malicious web visitor 133 | 134 | A web visitor, either human or bot, could attempt brute force visiting all possible alias endpoints, in order to build a dataset of all SSB IDs and claimed aliases gathered at this room, potentially tracking profiles of these SSB IDs. Malicious web visitors can also attempt to connect with these target IDs as victims, and may use social engineering or impersonation tactics during [tunneled authentication](../Participation/Tunneled%20authentication.md). 135 | 136 | #### Malicious [room admin](../Stakeholders/Room%20admin.md) 137 | 138 | The room admin could tamper with the [alias database](Alias%20database.md) and provide fake information on this web endpoint, e.g. that a certain alias was claimed by a certain users. Although the [database signature](Alias%20database.md) exists to prevent this type of tampering, it is only verified when performing [alias consumption](Alias%20consumption.md). For web visitors who only want to know which SSB ID corresponds to an alias, and only that, these visitors must trust the room administrator, who could provide inauthentic information. 139 | -------------------------------------------------------------------------------- /docs/Appendix/Readme.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Appendix -------------------------------------------------------------------------------- /docs/Appendix/muxrpc.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## List of new muxrpc APIs 8 | 9 | - async 10 | - `room.metadata()` 11 | - `room.registerAlias(alias, signature)` 12 | - `room.revokeAlias(alias)` 13 | - source 14 | - `room.attendants()` -------------------------------------------------------------------------------- /docs/Appendix/ssb-uris.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## List of new SSB URIs 8 | 9 | - `ssb:experimental?action=consume-alias&alias=${alias}&userId=${userId}&signature=${signature}&roomId=${roomId}&multiserverAddress=${roomMsAddr}` -------------------------------------------------------------------------------- /docs/Misc/External resolution.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # External alias resolution 8 | 9 | (DEPRECATED DOCUMENT BUT KEPT HERE FOR ARCHIVAL PURPOSES) 10 | 11 | When an [external user](../Stakeholders/External%20user.md) who knows an [internal user](../Stakeholders/Internal%20user.md) with an alias wishes to [connect](../Participation/Tunneled%20connection.md) with them, they must first *resolve the full alias*. 12 | 13 | ## Rough spec 14 | 15 | It's done with HTTPS requests following the WebFinger spec and `acct:` spec. The **input** is the [full alias](Full%20alias%20string.md) and the **output** is an [ssb-tunnel](https://github.com/ssbc/ssb-tunnel) `tunnel` address. 16 | 17 | ## Detailed spec TO-DO 18 | 19 | TO-DO Make UML diagram, see [sequenceDiagram example](../Misc/sequenceDiagram%20example.md). 20 | 21 | ## Security considerations 22 | 23 | ### Malicious [external users](../Stakeholders/External%20user.md) and [spiders](https://en.wikipedia.org/wiki/Web_crawler) 24 | 25 | All of [WebFinger's security considerations](https://tools.ietf.org/html/rfc7033#section-9), particularly how a malicious node can harvest resolved aliases by picking alias strings at random or brute force. For privacy considerations, both the full alias string and the resolved tunnel address should be considered effectively public information. 26 | 27 | ### Malicious [room admin](../Stakeholders/Room%20admin.md) 28 | 29 | The room admin receiving a WebFinger request could log and track IP addresses, session duration, and other metadata from WebFinger clients. 30 | 31 | 32 | ## See also 33 | 34 | - [WebFinger.net](https://webfinger.net/) 35 | - [Mastodon's WebFinger](https://docs.joinmastodon.org/spec/webfinger/) 36 | - [RFC 7033 (WebFinger spec)](https://tools.ietf.org/html/rfc7033) 37 | - [RFC 7565 (`acct:` URI spec)](https://tools.ietf.org/html/rfc7565) -------------------------------------------------------------------------------- /docs/Misc/muxrpc alias registration.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Alias resolution 8 | 9 | (DEPRECATED DOCUMENT BUT KEPT HERE FOR ARCHIVAL PURPOSES) 10 | 11 | ## Rough spec (muxrpc) 12 | 13 | 1. An internal user with SSB ID `feedId` and a room server with SSB ID `roomId` are connected to each other via secret-handshake 14 | 1. The internal user calls a specific [muxrpc](https://github.com/ssb-js/muxrpc/) API `registerAlias(alias, sig)` at the room server 15 | - `alias` is a supposed to be a string, a candidate [alias string](Alias%20string.md) 16 | - `sig` is a cryptographic signature covering `roomId`, `feedId`, and `alias` 17 | 1. The room checks whether that `alias` is valid (see spec in [Alias string](Alias%20string.md)) 18 | 1. If it is invalid, reply with an error 19 | 1. Else, proceed (below) 20 | 1. The room checks whether there already exists an entry in the [Alias database](Alias%20database.md) associated with this `feedId` 21 | 1. If there is, reply with an error 22 | 1. Else, proceed (below) 23 | 1. The room checks whether there already exists an entry in the [Alias database](Alias%20database.md) with the *key* `alias` 24 | 1. If it is registered, reply with an error 25 | 1. Else, proceed (below) 26 | 1. The room adds an entry to its [Alias database](Alias%20database.md) for `key=alias` & `value=feedId+sig` 27 | 1. (Optional) The room replies back to the client internal user via muxrpc with "success" (how? TO-DO) 28 | 1. (Optional) The internal user publishes an SSB msg of type `about` with a field for the newly registered alias (how? TO-DO) 29 | -------------------------------------------------------------------------------- /docs/Misc/sequenceDiagram example.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | Example UML diagram using Mermaid. 8 | 9 | ```mermaid 10 | sequenceDiagram 11 | participant A as Alice 12 | participant DOI as DO Installer 13 | participant R as New Room server 14 | 15 | A->>DOI: /GET HTML page 16 | Activate DOI 17 | Note over A,DOI: Complete steps on this page 18 | DOI->>R: Creates 19 | DOI-->>A: Page with link to URL of new room 20 | Deactivate DOI 21 | 22 | A->>R: /GET HTML page 23 | Activate R 24 | R-->>A: Page asking to configure room NAME and DESCRIPTION 25 | Deactivate R 26 | 27 | A->>R: /POST with NAME and DESCRIPTION 28 | Activate R 29 | R-->>A: Default page showing room's info and SSB invite 30 | Deactivate R 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /docs/Participation/Attendants.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Attendants API 8 | 9 | Internal users can discover about the presence of other internal users currently online at the room. This gives them the opportunity to choose to establish a [tunneled connection](Tunneled%20connection.md). 10 | 11 | ### Specification 12 | 13 | The muxrpc API `room.attendants` is a `source` method that streams JSON objects of three different schemas: **state** objects, **joined** objects, and **left** objects. 14 | 15 | There are no input arguments expected on this method. 16 | 17 | **State objects** 18 | 19 | When the user subscribes to the `room.attendants` stream, the first event **MUST** be of type "state", matching the JSON schema below: 20 | 21 | ```json 22 | { 23 | "$schema": "http://json-schema.org/draft-07/schema#", 24 | "$id": "https://github.com/ssb-ngi-pointer/rooms2#muxrpc-room-attendants-state", 25 | "type": "object", 26 | "properties": { 27 | "type": { 28 | "title": "Event type", 29 | "type": "string", 30 | "pattern": "^(state)$" 31 | }, 32 | "ids": { 33 | "title": "SSB IDs of attendants", 34 | "description": "A list of SSB IDs of all internal users currently online", 35 | "type": "array", 36 | "uniqueItems": true, 37 | "items": { 38 | "type": "string" 39 | } 40 | } 41 | }, 42 | "required": ["type", "ids"] 43 | } 44 | ``` 45 | 46 | **Joined objects** 47 | 48 | Whenever an internal user becomes online in the room, an event matching the following JSON schema below **MUST** be sent through the stream: 49 | 50 | ```json 51 | { 52 | "$schema": "http://json-schema.org/draft-07/schema#", 53 | "$id": "https://github.com/ssb-ngi-pointer/rooms2#muxrpc-room-attendants-joined", 54 | "type": "object", 55 | "properties": { 56 | "type": { 57 | "title": "Event type", 58 | "type": "string", 59 | "pattern": "^(joined)$" 60 | }, 61 | "id": { 62 | "title": "SSB ID", 63 | "description": "SSB ID of the attendant who just joined", 64 | "type": "string" 65 | } 66 | }, 67 | "required": ["type", "id"] 68 | } 69 | ``` 70 | 71 | **Left objects** 72 | 73 | Whenever an internal user ceases to be online in the room, an event matching the following JSON schema below **MUST** be sent through the stream: 74 | 75 | ```json 76 | { 77 | "$schema": "http://json-schema.org/draft-07/schema#", 78 | "$id": "https://github.com/ssb-ngi-pointer/rooms2#muxrpc-room-attendants-left", 79 | "type": "object", 80 | "properties": { 81 | "type": { 82 | "title": "Event type", 83 | "type": "string", 84 | "pattern": "^(left)$" 85 | }, 86 | "id": { 87 | "title": "SSB ID", 88 | "description": "SSB ID of the attendant who just left", 89 | "type": "string" 90 | } 91 | }, 92 | "required": ["type", "id"] 93 | } 94 | ``` 95 | 96 | -------------------------------------------------------------------------------- /docs/Participation/Internal user authentication.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Internal user authentication 8 | 9 | In rooms where the [privacy mode](../Setup/Privacy%20modes.md) is not *open*, not all SSB users who connect to the room are [internal users](../Stakeholders/Internal%20user.md). The room thus needs a way to authenticate the user before granting them a [tunnel address](Tunnel%20addresses.md). 10 | 11 | ### Specification 12 | 13 | When the room receives an incoming secret-handshake connection from Alice, it checks the [internal user registry](Internal%20user%20registry.md), looking for the entry corresponding to Alice's ID. If there is an entry, Alice is recognized as an internal user, granting her a [tunnel address](Tunnel%20addresses.md). Otherwise, the room recognizes Alice as an [external user](../Stakeholders/External%20user.md) and does not grant Alice a tunnel address. 14 | 15 | In either case, whether Alice is an internal or external user, the secret-handshake and muxrpc connection is allowed to remain up, because external users are allowed to [consume aliases](../Alias/Alias%20consumption.md) and create [tunneled connections](Tunneled%20connection.md) with internal users. The exception to the above is when the room is in [*Restricted* mode](../Setup/Privacy%20modes.md), in which case only internal users are allowed to maintain a secret-handshake and muxrpc connection. 16 | 17 | ### Security considerations 18 | 19 | #### Malicious [room admin](../Stakeholders/Room%20admin.md) 20 | 21 | The room software could be modified by the room admin to not authenticate some users as internal users. 22 | -------------------------------------------------------------------------------- /docs/Participation/Internal user registry.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Internal user registry 8 | 9 | The *internal user registry* is a database the room manages, keeping records of which SSB users are [internal users](../Stakeholders/Internal%20user.md). It is a simple list or table, where each entry refers to an internal user, and must contain at least the SSB ID for that user. 10 | -------------------------------------------------------------------------------- /docs/Participation/Invites.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Invites 8 | 9 | When [joining](Joining.md) a *Community* room or *Restricted* room, [internal users](../Stakeholders/Internal%20user.md) create invites. An invite can be sent to anyone who is not yet an internal user, and who can then "claim" the invite in order to become a new internal user of the room. 10 | 11 | A room server **SHOULD** employ [SSB HTTP Invites](https://github.com/ssbc/ssb-http-invite-spec). 12 | -------------------------------------------------------------------------------- /docs/Participation/Joining.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Joining 8 | 9 | "Joining a room" means the process where an [external user](../Stakeholders/External%20user.md) becomes an [internal user](../Stakeholders/Internal%20user.md). 10 | 11 | ### Specification 12 | 13 | The joining process is different for each [Privacy mode](../Setup/Privacy%20modes.md): 14 | 15 | - **Open:** 16 | 1. An [external user](../Stakeholders/External%20user.md), Alice, acquires the open *invite code* either through the room's public website or via other means 17 | 1. Alice consumes the invite code in her SSB app that supports being a room client 18 | 1. The room accepts the connection from Alice and immediately grants her a [tunnel address](Tunnel%20addresses.md) 19 | 1. Alice has become an [internal user](../Stakeholders/Internal%20user.md) 20 | - **Community:** 21 | 1. An [internal user](../Stakeholders/Internal%20user.md), Bob, signs into the room's [web dashboard](../Setup/Web%20Dashboard.md) where he creates a one-time invite code in the form of an [invite link](Invites.md), provided by the dashboard. 22 | 1. Bob informs an [external user](../Stakeholders/External%20user.md), Alice, of the invite link 23 | 1. Alice consumes the invite according to the [invites specification](Invites.md) 24 | 1. Alice has become an [internal user](../Stakeholders/Internal%20user.md) 25 | - **Restricted:** 26 | 1. A [moderator](../Stakeholders/Moderator.md), Carla, signs into the room's [web dashboard](../Setup/Web%20Dashboard.md) where she creates a one-time invite code in the form of an [invite link](Invites.md), provided by the dashboard. 27 | 1. Bob informs an [external user](../Stakeholders/External%20user.md), Alice, of the invite link 28 | 1. Alice consumes the invite according to the [invites specification](Invites.md) 29 | 1. Alice has become an [internal user](../Stakeholders/Internal%20user.md) 30 | 31 | To summarize, in **Community** mode, all internal users can create invites while in **Restricted** mode only moderators can. **Open** mode means there always is an invite for all the users in the room. 32 | -------------------------------------------------------------------------------- /docs/Participation/Metadata.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Metadata API 8 | 9 | Clients, whether internal or external users, may need to know additional information about the room before interacting with it. For instance, they may need to know whether they are an internal user or not, and they may need to know what features the room has currently enabled. 10 | 11 | ### Specification 12 | 13 | The muxrpc API `room.metadata` is an `async` method that returns a JSON object listing information about the room. 14 | 15 | **Input**: zero arguments required 16 | 17 | **Output**: JSON body type, with the following JSON schema 18 | 19 | ```json 20 | { 21 | "$schema": "http://json-schema.org/draft-07/schema#", 22 | "$id": "https://github.com/ssb-ngi-pointer/rooms2#muxrpc-room-metadata", 23 | "type": "object", 24 | "properties": { 25 | "name": { 26 | "title": "Name of this room", 27 | "description": "The domain or hostname or arbitrary name of the room server", 28 | "type": "string" 29 | }, 30 | "membership": { 31 | "title": "Membership", 32 | "description": "Whether or not the client calling this muxrpc method is recognized as an internal user", 33 | "type": "boolean" 34 | }, 35 | "features": { 36 | "title": "Features", 37 | "description": "A list of features supported by this room", 38 | "type": "array", 39 | "uniqueItems": true, 40 | "items": { 41 | "enum": ["tunnel", "room1", "room2", "alias", "httpAuth", "httpInvite"] 42 | } 43 | } 44 | }, 45 | "required": ["name", "membership", "features"] 46 | } 47 | ``` 48 | 49 | The `features` array is particularly important, as it flags which features clients can use on the room. The semantics of each value in the *enum* are listed below: 50 | 51 | - `"tunnel"`: **MUST** be included in `features` only if users can establish [tunneled connections](Tunneled%20connection.md) with other users 52 | - `"room1"`: **MUST** be included only if the room server is fully compatible with Room 1.0, i.e. clients can interact with it in the same manner they interact with Room 1.0 servers. This means the server **MUST** operate with its [Privacy mode](../Setup/Privacy%20modes.md) set to "Open" 53 | - `"room2"`: **MUST** be included only if the room server supports muxrpc APIs under the namespace `room`, such as `room.metadata()` and `room.attendants` 54 | - `"alias"`: **MUST** be included only if the room server supports [Aliases](../Alias/Readme.md), i.e. muxrpc APIs `room.registerAlias`, `room.revokeAlias` and alias consumption 55 | - `"httpAuth"`: **MUST** be included only if the room server complies with the [SSB HTTP Authentication](https://github.com/ssb-ngi-pointer/ssb-http-auth-spec) specification 56 | - `"httpInvite"`: **MUST** be included only if the room server complies with the [SSB HTTP Invites](https://ssb-ngi-pointer.github.io/ssb-http-invite-spec/) specification 57 | -------------------------------------------------------------------------------- /docs/Participation/Readme.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Participation 8 | 9 | Before peers can connect to each other via a room server, they first need to become members, i.e. [internal users](../Stakeholders/Internal%20user.md). This section describes the different protocols used for establishing internal user participation. 10 | -------------------------------------------------------------------------------- /docs/Participation/Tunnel addresses.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Tunnel addresses 8 | 9 | To establish a [tunneled connection](Tunneled%20connection.md), the peer initiating it must know the *tunnel address* of the peer at the other side of the tunnel. 10 | 11 | ### Specification 12 | 13 | A tunnel address is a string conforming to the [multiserver-address](https://github.com/ssbc/multiserver-address) grammar. We say that "room M *grants* peer A a tunnel address" when room M allows other peers to request and establish [tunneled connections](Tunneled%20connection.md) with peer A, using the tunnel address to identify peer A. 14 | 15 | It consists of three parts and `:` as separators in between: 16 | 17 | - `tunnel` as a constant tag 18 | - SSB ID of the intermediary peer 19 | - SSB ID of the target peer 20 | 21 | ### Example 22 | 23 | Without spaces nor newlines: 24 | 25 | ``` 26 | tunnel:@7MG1hyfz8SsxlIgansud4LKM57IHIw2Okw 27 | /hvOdeJWw=.ed25519:@1b9KP8znF7A4i8wnSevBSK 28 | 2ZabI/Re4bYF/Vh3hXasQ=.ed25519 29 | ``` 30 | 31 | The tunnel address, being a multiserver address, can also contain a *transform* section, such as the common `shs` transform (without spaces nor newlines): 32 | 33 | ``` 34 | tunnel:@7MG1hyfz8SsxlIgansud4LKM57IHIw2Okw 35 | /hvOdeJWw=.ed25519:@1b9KP8znF7A4i8wnSevBSK 36 | 2ZabI/Re4bYF/Vh3hXasQ=.ed25519~shs:1b9KP8z 37 | nF7A4i8wnSevBSK2ZabI/Re4bYF/Vh3hXasQ= 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/Participation/Tunneled authentication.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Tunneled authentication 8 | 9 | Tunneled authentication is about making sure that SSB peers on the opposite end of a [tunneled connection](Tunneled%20connection.md) only allow the connection to occur if they follow the peer on the other side. Thus we need a way for peers to know who wants to open a tunneled connection and we should facilitate mutual follows to occur so that peers only create tunneled connections imbued with mutual interest. 10 | 11 | ### Specification 12 | 13 | Tunneled friend authentication is an algorithm or protocol that applies automatically without any user input from either end of the secret-handshake channel. This protocol should not apply for the intermediary peer, that is, the room server. 14 | 15 | When Alice receives a tunneled secret-handshake incoming connection from Bob, she automatically allows it if Alice checks that she follows Bob, or automatically cancels the connection if Alice checks that she does not follow Bob (or blocks Bob). Same is true reciprocically: Bob applies this rule for incoming connections from Alice. 16 | 17 | Thus tunneled authentication **requires mutual follows** ("friendship") before establishing a functioning [tunneled connection](Tunneled%20connection.md). 18 | 19 | When a denial of connection occurs, the peer that received the connection should be able to see (and thus locally log): (1) SSB ID of the intermediary peer (room) used, (2) SSB ID of the origin peer behind the intermediary, (3) (optionally) the address ([tunnel address](Tunnel%20addresses.md) or [alias endpoint URL](Web%20endpoint.md)) of the origin peer. 20 | 21 | The user that received the denied connection can then see this fact in their SSB app, and then they can make a conscious choice to either (1) follow the origin peer, or (2) connect to the origin peer (if (3) from the previous paragraph existed), or both. 22 | 23 | ### Implementation notes 24 | 25 | Note that in current room server implementation in JavaScript, [`opts.origin`](https://github.com/staltz/ssb-room/blob/e78d54887682664def36d48ca9e648fc609478e9/tunnel/server.js#L100) in the room is calculated from secret-handshake, so it can be trusted to be authentic. 26 | 27 | For the next version of rooms, if we want `opts.origin` to also contain the origin peer's address (ssb-tunnel address or alias endpoint), then we need other means of verifying that the origin address is authentic. E.g. if it's an [alias endpoint URL](../Alias/Web%20endpoint.md), maybe the receiving peer visits the alias JSON endpoint then [consumes the alias](../Alias/Alias%20consumption.md), or maybe the receiving peer takes the ssb-tunnel address and verifies that the ID matches with the secret-handshake-given ID. -------------------------------------------------------------------------------- /docs/Participation/Tunneled connection.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Tunneled connection 8 | 9 | A tunneled connection is an indirect connection between two peers assisted by an intermediary peer. Ideally, two peers could always connect with each other directly, but they often have unstable IP addresses behind NATs and firewalls, making it difficult to consistently and reliably establish connections. The purpose of the intermediary peer is to improve connection reliability, because these intermediary peers can be privileged nodes with public IP addresses, such as from hosting services. 10 | 11 | ### Specification 12 | 13 | Tunneled connections in SSB originated from the proof-of-concept [ssb-tunnel](https://github.com/ssbc/ssb-tunnel) module. Suppose A and B are clients of a intermediary server M. Peer A creates a conventional [handshake](https://ssbc.github.io/scuttlebutt-protocol-guide/#handshake) connection to M, and waits to receive tunnel connections. Peer B creates a conventional secret handshake connection to M, and then requests a tunneled connection to A through that conventional connection (B-M). Then, M calls A, creating a tunneled connection where one end is attached to A and the other end is attached to B's request. Finally, B uses the secret handshake to authenticate A. 14 | 15 | Notice that for the intermediary M, peer A is the server and B is the client (client calls, server answers) but M is just the portal. The tunneled connection is inside the outer (conventional) connections, which means it is encrypted twice with [box stream](https://ssbc.github.io/scuttlebutt-protocol-guide/#box-stream). This means A and B can mutually authenticate each other, and M cannot see the content of their connection. 16 | 17 | Diagram: 18 | 19 | ``` 20 | ,---, ,---, ,---, 21 | | |----->| |<----| | 22 | | A |<=====| M |<====| B | 23 | | |----->| |<----| | 24 | `---` `---` `---` 25 | ``` 26 | 27 | The arrows represent the direction of the connection – from the client, pointing to the server. Notice the M<=B connection is the same direction as the M<-B outer connection, but the A<=M connection is the opposite direction as the A->M outer connection. 28 | 29 | ### Security considerations 30 | 31 | #### Malicious [room admin](../Stakeholders/Room%20admin.md) 32 | 33 | The room admin could log and track all connection sessions for every tunneled connection, thus tracking the **IP addresses**, **timestamps**, **durations**, and **bandwidth** of interactions between [internal users](../Stakeholders/Internal%20user.md). The room admin could track which SSB users are interested in connecting with internal users, i.e. they can gather **social interest metadata**, which could be used to create a draft of a portion of the social graph. 34 | 35 | That said, because of encrypted tunneled secret-handshake channels, the room admin could not know the contents of data transmitted between the internal users. 36 | 37 | -------------------------------------------------------------------------------- /docs/Setup/Components.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Components 8 | 9 | A room server is defined by several components, which are systems that enable features, some of these are optional and some are required. 10 | 11 | ### Required 12 | 13 | - [Tunneled connection](../Participation/Tunneled%20connection.md) 14 | - [Tunnel addresses](../Participation/Tunnel%20addresses.md) 15 | - [Privacy modes](../Setup/Privacy%20modes.md) (at least the *Open* mode) 16 | - [Joining](../Participation/Joining.md) (for at least the *Open* mode) 17 | 18 | ### Optional 19 | 20 | - Other [Privacy modes](../Setup/Privacy%20modes.md) and respective ways of [joining](../Participation/Joining.md) 21 | - [Internal user authentication](../Participation/Internal%20user%20authentication.md) 22 | - [Tunneled authentication](../Participation/Tunneled%20authentication.md) 23 | - [Invites](../Participation/Invites.md) 24 | - [Web Dashboard](Web%20Dashboard.md) 25 | - [Aliases](../Alias/Readme.md) -------------------------------------------------------------------------------- /docs/Setup/Config database.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Config database 8 | 9 | The configuration database holds basic administrative data, readable only by [admins](../Stakeholders/Room%20admin.md) and (indirectly via the [dashboard](Web%20Dashboard.md)) by [moderators](../Stakeholders/Moderator.md). 10 | 11 | ### Specification 12 | 13 | The database should contain these data points: 14 | 15 | - Which [privacy mode](../Setup/Privacy%20modes.md) is selected 16 | - List of SSB IDs of [moderators](../Stakeholders/Moderator.md) 17 | - List of blocked SSB IDs 18 | - Name of the room (a short string) 19 | - Description for the room (not too long string) 20 | -------------------------------------------------------------------------------- /docs/Setup/Privacy modes.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Privacy modes 8 | 9 | A room server should allow the [room admin](../Stakeholders/Room%20admin.md) or a [moderator](../Stakeholders/Moderator.md) to configure which users can become [internal user](../Stakeholders/Internal%20user.md). 10 | 11 | ### Specification 12 | 13 | There are three strategies recommended as policies to [join](../Participation/Joining.md) the room, known as privacy modes: 14 | 15 | - **Open**: invite codes are openly known, similar to [ssb-room v1](https://github.com/staltz/ssb-room) 16 | - **Community**: only [internal users](../Stakeholders/Internal%20user.md) can invite [external users](../Stakeholders/External%20user.md) to become an internal users 17 | - **Restricted**: only [admins](../Stakeholders/Room%20admin.md) and [moderators](../Stakeholders/Moderator.md) can invite [external users](../Stakeholders/External%20user.md) to become an internal users, and [aliases](../Alias/Readme.md) are not supported 18 | 19 | **Joining:** To become a member of the room, peers need to [join the room](../Participation/Joining.md). 20 | -------------------------------------------------------------------------------- /docs/Setup/Readme.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Setup 8 | 9 | There are different ways a room server can be configured. 10 | -------------------------------------------------------------------------------- /docs/Setup/Web Dashboard.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Web Dashboard 8 | 9 | This is a WWW interface that allows [moderators](../Stakeholders/Moderator.md) to sign-in and perform some privileged actions. The sign-in method **SHOULD** be [SSB HTTP Authentication](https://github.com/ssb-ngi-pointer/ssb-http-auth-spec) but it **MAY** be username/password or other methods. [Internal users](../Stakeholders/Internal%20user.md) can also sign-in and perform basic actions such as [create invites for other users to join](Joining.md). 10 | 11 | ### Specification 12 | 13 | The dashboard grants [moderators](../Stakeholders/Moderator.md) with features and powers such as: 14 | 15 | - Block SSB IDs from connecting with this room, meaning two things: 16 | - If they were an [internal user](../Stakeholders/Internal%20user.md), they get demoted to [external user](../Stakeholders/External%20user.md) 17 | - Even if they were an [external user](../Stakeholders/External%20user.md), the room server will reject new attempts of secret-handshake connections 18 | - Unblock SSB IDs that are blocked 19 | - Nominate other internal users to become moderators too 20 | - View the list of aliases according to the [Alias database](../Alias/Alias%20database.md) 21 | - Revoke aliases by removing an entry from the [Alias database](../Alias/Alias%20database.md) 22 | - Change the [privacy mode](../Setup/Privacy%20modes.md) of the room 23 | - View other technical measurements such as bandwidth used, storage used by the databases, etc 24 | 25 | The dashboard grants [internal users](../Stakeholders/Internal%20user.md) basic features such as: 26 | 27 | - Register an alias for themselves 28 | - Revoke an alias for themselves 29 | - Create an invite for [external users](../Stakeholders/External%20user.md) to [join the room](../Participation/Joining.md) if the room is running in [Community mode](../Setup/Privacy%20modes.md) 30 | 31 | ### Security considerations 32 | 33 | #### HTTPS vulnerabilities 34 | 35 | Typically SSB has not relied on the certificate architecture underlying TLS, and has had no interoperability with HTTPS. Since rooms 2.0 rely on HTTPS, then the vulnerabilities inherent in TLS, such weak certificate authorities that can enable man-in-the-middle attacks. In such scenarios, with room servers there would be possibility for man-in-the-middle attacks when claiming invites (redirecting to another multiserver address), when [resolving aliases](../Alias/Alias%20consumption.md) (impersonating the alias owner), or when performing sign-in with SSB identities. 36 | 37 | To mitigate these types of attacks, implementations and deployments of rooms should make a conscious choice of a trustworthy certificate authority. 38 | 39 | #### Malicious [moderator](../Stakeholders/Moderator.md) 40 | 41 | Moderators obviously hold some power, and this power may be abused through unfair blocks, unfair revoking of aliases. In many cases, fairness is subjective, and is understood to be an essential compromise of having moderation to begin with. So in this section we will focus our attention on unusual security issues with moderation. 42 | 43 | A moderator has the right to nominate other internal users to become moderators, and this could lead to a proliferation of moderators, which increases the possibility that one of these moderators abuses their powers. On the other hand, there has been many maintainers and npm owners in the [SSBC](https://github.com/ssbc/) (e.g. 32 GitHub org members and 17 npm owners for the cornerstone [`ssb-db`](https://www.npmjs.com/package/ssb-db) package), we also know that the presence of many moderators may also help to *decrease* the possibility of abuse, because asymmetry of privilege is reduced. -------------------------------------------------------------------------------- /docs/Stakeholders/External user.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## External user 8 | 9 | Any SSB user who is not an [internal user](Internal%20user.md) of the room (i.e. do not have a usable [tunnel address](../Participation/Tunnel%20addresses.md) referencing the room), but may still interact with the room server in meaningful ways, for instance with [tunneled connections](../Participation/Tunneled%20connection.md), [alias endpoints](../Alias/Web%20endpoint.md) or [alias consumption](../Alias/Alias%20consumption.md). -------------------------------------------------------------------------------- /docs/Stakeholders/Internal user.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Internal user 8 | 9 | SSB user who accesses the room server and is considered *internal* because they have already [joined](../Participation/Joining.md) the room and may even have registered an [alias](../Alias/Readme.md) in the room. 10 | 11 | ### Specification 12 | 13 | **Definition:** an *internal user* of a room is any SSB ID for which the room grants a [tunnel address](../Participation/Tunnel%20addresses.md). In other words, if an SSB ID is *reachable* via a [tunneled connection](../Participation/Tunneled%20connection.md) through a room server, then they are considered an internal user of that room. 14 | 15 | **Becoming an internal user:** read more about that in [Joining a room](../Participation/Joining.md). 16 | -------------------------------------------------------------------------------- /docs/Stakeholders/Moderator.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Moderator 8 | 9 | A moderator is an [internal user](Internal%20user.md) that has acquired special privileges in the [web dashboard](../Setup/Web%20Dashboard.md) and actions allowed by the dashboard. 10 | 11 | Moderators can use sign-in to access the [dashboard](../Setup/Web%20Dashboard.md). -------------------------------------------------------------------------------- /docs/Stakeholders/Readme.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # Stakeholders 8 | 9 | Persons or organizations that are involved or engaged in or around room servers. They may hold responsibilities or powers, and may cause harm to other stakeholders when their responsibilities or powers are abused. They hold interest in engaging with other stakeholders while managing the risk for harm associated with engagement. Harm mitigation such as [Privacy modes](../Setup/Privacy%20modes.md) is important when discussing stakeholders. 10 | -------------------------------------------------------------------------------- /docs/Stakeholders/Room admin.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Room admin 8 | 9 | Person or organization responsible for operating the room server, and has full access rights over the server's resources such as logs, disk, memory, etc. In other words, this person or organization physically owns the room server or has SSH access to the remote server hosted in some PaaS cloud provider. 10 | 11 | Typically, the admin possesses an SSB ID (it's very common, but not necessarily always the case), and is also a [moderator](Moderator.md) in the room. -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 40 | 41 | 42 | 43 | 44 | 49 |

SSB Rooms 2.0

50 |

Revision: 2022-10-10

51 |

Author: Andre Medeiros contact@staltz.com

52 |

License: This work is licensed under a Creative Commons Attribution 4.0 International License.

53 |

Abstract

54 |

A room server is an SSB peer with privileged internet presence (for instance, not behind a NAT layer) which allows its clients to perform tunneled connections wich each other. For practical purposes, room clients seem to be connected to each other directly, but the room is an intermediary. Connections between server and client are end-to-end encrypted via secret-handshake, as well as in tunneled connections between room clients, so that the room server cannot eavesdrop on the payloads in the tunneled connections. This document describes new capabilities for rooms, such as user aliases, privacy modes, and tunneled authentication.

55 |

Terminology

56 |

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

57 |

Table of contents

58 | 105 |

Stakeholders

106 |

Persons or organizations that are involved or engaged in or around room servers. They may hold responsibilities or powers, and may cause harm to other stakeholders when their responsibilities or powers are abused. They hold interest in engaging with other stakeholders while managing the risk for harm associated with engagement. Harm mitigation such as Privacy modes is important when discussing stakeholders.

107 | 112 |

Room admin

113 |

Person or organization responsible for operating the room server, and has full access rights over the server's resources such as logs, disk, memory, etc. In other words, this person or organization physically owns the room server or has SSH access to the remote server hosted in some PaaS cloud provider.

114 |

Typically, the admin possesses an SSB ID (it's very common, but not necessarily always the case), and is also a moderator in the room.

115 | 120 |

Internal user

121 |

SSB user who accesses the room server and is considered internal because they have already joined the room and may even have registered an alias in the room.

122 |

Specification

123 |

Definition: an internal user of a room is any SSB ID for which the room grants a tunnel address. In other words, if an SSB ID is reachable via a tunneled connection through a room server, then they are considered an internal user of that room.

124 |

Becoming an internal user: read more about that in Joining a room.

125 | 130 |

External user

131 |

Any SSB user who is not an internal user of the room (i.e. do not have a usable tunnel address referencing the room), but may still interact with the room server in meaningful ways, for instance with tunneled connections, alias endpoints or alias consumption.

132 | 137 |

Moderator

138 |

A moderator is an internal user that has acquired special privileges in the web dashboard and actions allowed by the dashboard.

139 |

Moderators can use sign-in to access the dashboard.

140 | 145 |

Setup

146 |

There are different ways a room server can be configured.

147 | 152 |

Components

153 |

A room server is defined by several components, which are systems that enable features, some of these are optional and some are required.

154 |

Required

155 | 161 |

Optional

162 | 170 | 175 |

Privacy modes

176 |

A room server should allow the room admin or a moderator to configure which users can become internal user.

177 |

Specification

178 |

There are three strategies recommended as policies to join the room, known as privacy modes:

179 | 184 |

Joining: To become a member of the room, peers need to join the room.

185 | 190 |

Config database

191 |

The configuration database holds basic administrative data, readable only by admins and (indirectly via the dashboard) by moderators.

192 |

Specification

193 |

The database should contain these data points:

194 | 201 | 206 |

Web Dashboard

207 |

This is a WWW interface that allows moderators to sign-in and perform some privileged actions. The sign-in method SHOULD be SSB HTTP Authentication but it MAY be username/password or other methods. Internal users can also sign-in and perform basic actions such as create invites for other users to join.

208 |

Specification

209 |

The dashboard grants moderators with features and powers such as:

210 | 224 |

The dashboard grants internal users basic features such as:

225 | 230 |

Security considerations

231 |
HTTPS vulnerabilities
232 |

Typically SSB has not relied on the certificate architecture underlying TLS, and has had no interoperability with HTTPS. Since rooms 2.0 rely on HTTPS, then the vulnerabilities inherent in TLS, such weak certificate authorities that can enable man-in-the-middle attacks. In such scenarios, with room servers there would be possibility for man-in-the-middle attacks when claiming invites (redirecting to another multiserver address), when resolving aliases (impersonating the alias owner), or when performing sign-in with SSB identities.

233 |

To mitigate these types of attacks, implementations and deployments of rooms should make a conscious choice of a trustworthy certificate authority.

234 |
Malicious moderator
235 |

Moderators obviously hold some power, and this power may be abused through unfair blocks, unfair revoking of aliases. In many cases, fairness is subjective, and is understood to be an essential compromise of having moderation to begin with. So in this section we will focus our attention on unusual security issues with moderation.

236 |

A moderator has the right to nominate other internal users to become moderators, and this could lead to a proliferation of moderators, which increases the possibility that one of these moderators abuses their powers. On the other hand, there has been many maintainers and npm owners in the SSBC (e.g. 32 GitHub org members and 17 npm owners for the cornerstone ssb-db package), we also know that the presence of many moderators may also help to decrease the possibility of abuse, because asymmetry of privilege is reduced.

237 | 242 |

Participation

243 |

Before peers can connect to each other via a room server, they first need to become members, i.e. internal users. This section describes the different protocols used for establishing internal user participation.

244 | 249 |

Joining

250 |

"Joining a room" means the process where an external user becomes an internal user.

251 |

Specification

252 |

The joining process is different for each Privacy mode:

253 | 279 |

To summarize, in Community mode, all internal users can create invites while in Restricted mode only moderators can. Open mode means there always is an invite for all the users in the room.

280 | 285 |

Internal user registry

286 |

The internal user registry is a database the room manages, keeping records of which SSB users are internal users. It is a simple list or table, where each entry refers to an internal user, and must contain at least the SSB ID for that user.

287 | 292 |

Internal user authentication

293 |

In rooms where the privacy mode is not open, not all SSB users who connect to the room are internal users. The room thus needs a way to authenticate the user before granting them a tunnel address.

294 |

Specification

295 |

When the room receives an incoming secret-handshake connection from Alice, it checks the internal user registry, looking for the entry corresponding to Alice's ID. If there is an entry, Alice is recognized as an internal user, granting her a tunnel address. Otherwise, the room recognizes Alice as an external user and does not grant Alice a tunnel address.

296 |

In either case, whether Alice is an internal or external user, the secret-handshake and muxrpc connection is allowed to remain up, because external users are allowed to consume aliases and create tunneled connections with internal users. The exception to the above is when the room is in Restricted mode, in which case only internal users are allowed to maintain a secret-handshake and muxrpc connection.

297 |

Security considerations

298 |
Malicious room admin
299 |

The room software could be modified by the room admin to not authenticate some users as internal users.

300 | 305 |

Invites

306 |

When joining a Community room or Restricted room, internal users create invites. An invite can be sent to anyone who is not yet an internal user, and who can then "claim" the invite in order to become a new internal user of the room.

307 |

A room server SHOULD employ SSB HTTP Invites.

308 | 313 |

Tunnel addresses

314 |

To establish a tunneled connection, the peer initiating it must know the tunnel address of the peer at the other side of the tunnel.

315 |

Specification

316 |

A tunnel address is a string conforming to the multiserver-address grammar. We say that "room M grants peer A a tunnel address" when room M allows other peers to request and establish tunneled connections with peer A, using the tunnel address to identify peer A.

317 |

It consists of three parts and : as separators in between:

318 | 323 |

Example

324 |

Without spaces nor newlines:

325 |
tunnel:@7MG1hyfz8SsxlIgansud4LKM57IHIw2Okw
326 | /hvOdeJWw=.ed25519:@1b9KP8znF7A4i8wnSevBSK
327 | 2ZabI/Re4bYF/Vh3hXasQ=.ed25519
328 | 
329 |

The tunnel address, being a multiserver address, can also contain a transform section, such as the common shs transform (without spaces nor newlines):

330 |
tunnel:@7MG1hyfz8SsxlIgansud4LKM57IHIw2Okw
331 | /hvOdeJWw=.ed25519:@1b9KP8znF7A4i8wnSevBSK
332 | 2ZabI/Re4bYF/Vh3hXasQ=.ed25519~shs:1b9KP8z
333 | nF7A4i8wnSevBSK2ZabI/Re4bYF/Vh3hXasQ=
334 | 
335 | 340 |

Tunneled connection

341 |

A tunneled connection is an indirect connection between two peers assisted by an intermediary peer. Ideally, two peers could always connect with each other directly, but they often have unstable IP addresses behind NATs and firewalls, making it difficult to consistently and reliably establish connections. The purpose of the intermediary peer is to improve connection reliability, because these intermediary peers can be privileged nodes with public IP addresses, such as from hosting services.

342 |

Specification

343 |

Tunneled connections in SSB originated from the proof-of-concept ssb-tunnel module. Suppose A and B are clients of a intermediary server M. Peer A creates a conventional handshake connection to M, and waits to receive tunnel connections. Peer B creates a conventional secret handshake connection to M, and then requests a tunneled connection to A through that conventional connection (B-M). Then, M calls A, creating a tunneled connection where one end is attached to A and the other end is attached to B's request. Finally, B uses the secret handshake to authenticate A.

344 |

Notice that for the intermediary M, peer A is the server and B is the client (client calls, server answers) but M is just the portal. The tunneled connection is inside the outer (conventional) connections, which means it is encrypted twice with box stream. This means A and B can mutually authenticate each other, and M cannot see the content of their connection.

345 |

Diagram:

346 |
,---,      ,---,     ,---,
347 | |   |----->|   |<----|   |
348 | | A |<=====| M |<====| B |
349 | |   |----->|   |<----|   |
350 | `---`      `---`     `---`
351 | 
352 |

The arrows represent the direction of the connection – from the client, pointing to the server. Notice the M<=B connection is the same direction as the M<-B outer connection, but the A<=M connection is the opposite direction as the A->M outer connection.

353 |

Security considerations

354 |
Malicious room admin
355 |

The room admin could log and track all connection sessions for every tunneled connection, thus tracking the IP addresses, timestamps, durations, and bandwidth of interactions between internal users. The room admin could track which SSB users are interested in connecting with internal users, i.e. they can gather social interest metadata, which could be used to create a draft of a portion of the social graph.

356 |

That said, because of encrypted tunneled secret-handshake channels, the room admin could not know the contents of data transmitted between the internal users.

357 | 362 |

Tunneled authentication

363 |

Tunneled authentication is about making sure that SSB peers on the opposite end of a tunneled connection only allow the connection to occur if they follow the peer on the other side. Thus we need a way for peers to know who wants to open a tunneled connection and we should facilitate mutual follows to occur so that peers only create tunneled connections imbued with mutual interest.

364 |

Specification

365 |

Tunneled friend authentication is an algorithm or protocol that applies automatically without any user input from either end of the secret-handshake channel. This protocol should not apply for the intermediary peer, that is, the room server.

366 |

When Alice receives a tunneled secret-handshake incoming connection from Bob, she automatically allows it if Alice checks that she follows Bob, or automatically cancels the connection if Alice checks that she does not follow Bob (or blocks Bob). Same is true reciprocically: Bob applies this rule for incoming connections from Alice.

367 |

Thus tunneled authentication requires mutual follows ("friendship") before establishing a functioning tunneled connection.

368 |

When a denial of connection occurs, the peer that received the connection should be able to see (and thus locally log): (1) SSB ID of the intermediary peer (room) used, (2) SSB ID of the origin peer behind the intermediary, (3) (optionally) the address (tunnel address or alias endpoint URL) of the origin peer.

369 |

The user that received the denied connection can then see this fact in their SSB app, and then they can make a conscious choice to either (1) follow the origin peer, or (2) connect to the origin peer (if (3) from the previous paragraph existed), or both.

370 |

Implementation notes

371 |

Note that in current room server implementation in JavaScript, opts.origin in the room is calculated from secret-handshake, so it can be trusted to be authentic.

372 |

For the next version of rooms, if we want opts.origin to also contain the origin peer's address (ssb-tunnel address or alias endpoint), then we need other means of verifying that the origin address is authentic. E.g. if it's an alias endpoint URL, maybe the receiving peer visits the alias JSON endpoint then consumes the alias, or maybe the receiving peer takes the ssb-tunnel address and verifies that the ID matches with the secret-handshake-given ID.

373 | 378 |

Metadata API

379 |

Clients, whether internal or external users, may need to know additional information about the room before interacting with it. For instance, they may need to know whether they are an internal user or not, and they may need to know what features the room has currently enabled.

380 |

Specification

381 |

The muxrpc API room.metadata is an async method that returns a JSON object listing information about the room.

382 |

Input: zero arguments required

383 |

Output: JSON body type, with the following JSON schema

384 |
{
385 |   "$schema": "http://json-schema.org/draft-07/schema#",
386 |   "$id": "https://github.com/ssb-ngi-pointer/rooms2#muxrpc-room-metadata",
387 |   "type": "object",
388 |   "properties": {
389 |     "name": {
390 |       "title": "Name of this room",
391 |       "description": "The domain or hostname or arbitrary name of the room server",
392 |       "type": "string"
393 |     },
394 |     "membership": {
395 |       "title": "Membership",
396 |       "description": "Whether or not the client calling this muxrpc method is recognized as an internal user",
397 |       "type": "boolean"
398 |     },
399 |     "features": {
400 |       "title": "Features",
401 |       "description": "A list of features supported by this room",
402 |       "type": "array",
403 |       "uniqueItems": true,
404 |       "items": {
405 |         "enum": ["tunnel", "room1", "room2", "alias", "httpAuth", "httpInvite"]
406 |       }
407 |     }
408 |   },
409 |   "required": ["name", "membership", "features"]
410 | }
411 | 
412 |

The features array is particularly important, as it flags which features clients can use on the room. The semantics of each value in the enum are listed below:

413 | 421 | 426 |

Attendants API

427 |

Internal users can discover about the presence of other internal users currently online at the room. This gives them the opportunity to choose to establish a tunneled connection.

428 |

Specification

429 |

The muxrpc API room.attendants is a source method that streams JSON objects of three different schemas: state objects, joined objects, and left objects.

430 |

There are no input arguments expected on this method.

431 |

State objects

432 |

When the user subscribes to the room.attendants stream, the first event MUST be of type "state", matching the JSON schema below:

433 |
{
434 |   "$schema": "http://json-schema.org/draft-07/schema#",
435 |   "$id": "https://github.com/ssb-ngi-pointer/rooms2#muxrpc-room-attendants-state",
436 |   "type": "object",
437 |   "properties": {
438 |     "type": {
439 |       "title": "Event type",
440 |       "type": "string",
441 |       "pattern": "^(state)$"
442 |     },
443 |     "ids": {
444 |       "title": "SSB IDs of attendants",
445 |       "description": "A list of SSB IDs of all internal users currently online",
446 |       "type": "array",
447 |       "uniqueItems": true,
448 |       "items": {
449 |         "type": "string"
450 |       }
451 |     }
452 |   },
453 |   "required": ["type", "ids"]
454 | }
455 | 
456 |

Joined objects

457 |

Whenever an internal user becomes online in the room, an event matching the following JSON schema below MUST be sent through the stream:

458 |
{
459 |   "$schema": "http://json-schema.org/draft-07/schema#",
460 |   "$id": "https://github.com/ssb-ngi-pointer/rooms2#muxrpc-room-attendants-joined",
461 |   "type": "object",
462 |   "properties": {
463 |     "type": {
464 |       "title": "Event type",
465 |       "type": "string",
466 |       "pattern": "^(joined)$"
467 |     },
468 |     "id": {
469 |       "title": "SSB ID",
470 |       "description": "SSB ID of the attendant who just joined",
471 |       "type": "string"
472 |     }
473 |   },
474 |   "required": ["type", "id"]
475 | }
476 | 
477 |

Left objects

478 |

Whenever an internal user ceases to be online in the room, an event matching the following JSON schema below MUST be sent through the stream:

479 |
{
480 |   "$schema": "http://json-schema.org/draft-07/schema#",
481 |   "$id": "https://github.com/ssb-ngi-pointer/rooms2#muxrpc-room-attendants-left",
482 |   "type": "object",
483 |   "properties": {
484 |     "type": {
485 |       "title": "Event type",
486 |       "type": "string",
487 |       "pattern": "^(left)$"
488 |     },
489 |     "id": {
490 |       "title": "SSB ID",
491 |       "description": "SSB ID of the attendant who just left",
492 |       "type": "string"
493 |     }
494 |   },
495 |   "required": ["type", "id"]
496 | }
497 | 
498 | 503 |

Alias

504 |

An alias (also known as "room alias") is a string that identifies an internal user, designed to be short and human-friendly, similar to email addresses and Mastodon WebFinger addresses. The purpose of aliases is to improve the user experience of accurately (1) identifying the internal user and (2) locating the internal user at a room server for the purpose of establishing a connection with them.

505 |

As an example, suppose Alice is an internal user of the room "Scuttlebutt EU". The room's domain is scuttlebutt.eu and Alice's alias is alice. Alice's alias endpoint is thus alice.scuttlebutt.eu.

506 |

In short,

507 | 514 | 519 |

Alias string

520 |

An internal user's alias, also known as "alias string", is used to uniquely (unique within the room server only) identify that internal user. This string is useful only within the context of the room, i.e. not globally identifiable.

521 |

Example

522 |

Suppose Alice is an internal user of the room "Scuttlebutt EU". Alice's alias could be one of these strings (non-exhaustive list):

523 | 528 |

Specification

529 |

The string should satisfy the same rules as domain "labels" as defined in RFC 1035.

530 | 535 |

Alias registration

536 |

An internal user who does not have an alias in the current room server can choose to register an alias. Not all internal users need to have aliases, so the process described here is optional.

537 |

Specification

538 |
    539 |
  1. An internal user with SSB ID feedId and a room server with SSB ID roomId are connected to each other via secret-handshake
  2. 540 |
  3. The internal user chooses a alias as a candidate alias string
  4. 541 |
  5. The internal user calls a specific muxrpc async API room.registerAlias(alias, signature) where signature is a cryptographic signature of the string =room-alias-registration:${roomId}:${feedId}:${alias} using feedId's cryptographic keypair, read more about it in the alias database spec
  6. 542 |
  7. The room, upon receiving the room.registerAlias muxrpc call, checks whether that alias is valid (see spec in Alias string) 543 |
      544 |
    1. If it is invalid, respond room.registerAlias with an error
    2. 545 |
    3. Else, proceed (below)
    4. 546 |
    547 |
  8. 548 |
  9. The room checks whether there already exists an entry in the Alias database with the key alias 549 |
      550 |
    1. If there is, respond room.registerAlias with an error
    2. 551 |
    3. Else, proceed (below)
    4. 552 |
    553 |
  10. 554 |
  11. The room adds an entry to its Alias database for key=alias & value=feedId+sig
  12. 555 |
  13. The room responds room.registerAlias with a string containing the Alias endpoint URL for the newly registered alias, indicating success
  14. 556 |
  15. The internal user receives the room's response to room.registerAlias 557 |
      558 |
    1. If it is an error, then (optionally) display a user interface failure to register the alias
    2. 559 |
    3. If it is a successful url string, then the internal user MAY publish an SSB msg of type about with a field listing all its aliases for various rooms, where this specific url is included. The specific schema of the message type is an application-level concern
    4. 560 |
    561 |
  16. 562 |
563 |

The above algorithm is also provided below as a UML sequence diagram:

564 |
565 | sequenceDiagram 566 | participant U as SSB peer 567 | participant R as Room server 568 | 569 | U->>R: (muxrpc async) `room.registerAlias(alias, signature)` 570 | alt `alias` is an invalid alias string
or already taken in the alias database
or other errors 571 | R-->>U: Respond room.registerAlias with an error 572 | opt 573 | U->>U: Display user interface error 574 | end 575 | else else 576 | R->>R: Adds an entry to
its alias database 577 | R-->>U: Respond `room.registerAlias` with a `url` string 578 | U->>U: Publishes an SSB
msg of type
`about` 579 | end 580 |
581 |

Security considerations

582 |
Malicious internal user
583 |

A malicious internal user could take many or all possible aliases in case the room accidentally allows such malicious user to become an internal user. Arguably, some room implementations could choose to allow only one alias per internal user, and that would still be compliant with this spec.

584 |

Malicious room admin

585 |

The room admin could reply with errors when technically the muxrpc should have succeeded, e.g. pretending that the alias candidate is invalid or pretending that it's already registered.

586 | 591 |

Alias revocation

592 |

When an internal user who has registered no longer wishes to have that alias associated with them anymore, they can perform alias revocation to remove that alias from the alias database.

593 |

Specification

594 |
    595 |
  1. An internal user with SSB ID feedId and a room server with SSB ID roomId are connected to each other via secret-handshake
  2. 596 |
  3. The internal user calls a specific muxrpc async API room.revokeAlias(alias, callback)
  4. 597 |
  5. The room, upon receiving the room.revokeAlias muxrpc call, checks whether there exists an entry in the Alias database for alias 598 |
      599 |
    1. If there is no entry, respond room.revokeAlias with an error
    2. 600 |
    3. Else, if there exists an entry for alias but it is not owned by feedId, respond room.revokeAlias with an error
    4. 601 |
    5. Else, proceed (below)
    6. 602 |
    603 |
  6. 604 |
  7. The room removes the entry from the Alias database associated with feedId
  8. 605 |
  9. The room responds room.revokeAlias with true, indicating success
  10. 606 |
  11. The internal user receives the room's response to room.revokeAlias 607 |
      608 |
    1. If it is an error, then (optionally) display a user interface failure to revoke the alias
    2. 609 |
    3. If it is true, then publish an SSB msg of type about with a field listing all its aliases for various rooms, where this specific alias is no longer listed. The specific schema of the message type is an application-level concern
    4. 610 |
    611 |
  12. 612 |
613 |

The above algorithm is also provided below as a UML sequence diagram:

614 |
615 | sequenceDiagram 616 | participant U as SSB peer 617 | participant R as Room server 618 | 619 | U->>R: (muxrpc async) `room.revokeAlias(alias)` 620 | alt `alias` does not exist, or other errors 621 | R-->>U: Respond room.revokeAlias with an error 622 | opt 623 | U->>U: Display user interface error 624 | end 625 | else else 626 | R->>R: Remove the entry in
the alias database 627 | R-->>U: Respond room.revokeAlias with `true` 628 | U->>U: Publishes an SSB
msg of type
`about` 629 | end 630 |
631 |

Security considerations

632 |
Malicious room admin
633 |

The room admin could refuse to remove the database entry, or could delete the database entry at will (before the internal user performs revocation). In other words, the internal user does not ultimately have power over the deletion of the alias entry from the alias database, it must trust the room admin regarding deletion.

634 | 639 |

Alias consumption

640 |

When an SSB user (external or internal) is connected to the room, and knows of another internal user's alias, they can perform alias consumption. After consumption is completed successfully, they authentically obtain the target user's SSB ID and can use it to start a tunneled connection.

641 |

Specification

642 |

The input for the consumption algorithm is the response from the web endpoint, which is (either through JSON or SSB URI): the room's multiserver address, roomId, userId, alias, and signature.

643 |
    644 |
  1. The SSB user verifies that the signature authentically matches roomId, userId and alias 645 |
      646 |
    1. If it is an invalid signature, interrupt alias consumption with a failure indicating that the alias association to the internal user userId was probably forged
    2. 647 |
    3. Else, proceed (below)
    4. 648 |
    649 |
  2. 650 |
  3. The SSB user acting as a client connects to the room's address and establishes a muxrpc connection
  4. 651 |
  5. The client can now use userId to initiate a tunneled connection with them
  6. 652 |
  7. (Optional and recommended) The client follows the userId, see tunneled authentication
  8. 653 |
654 | 659 |

Web endpoint

660 |

Once an alias is registered, it enables any web user to visit a web endpoint on the room server dedicated to that alias, for the purpose of telling the visitor what SSB ID does the alias resolve to, and with instructions on how to install an SSB app if the visitor doesn't have it yet.

661 |

The goal of this endpoint is to help any SSB user locate and identify the alias' owner by resolving the alias to: (1) the room's multiserver address, (2) the owner's SSB ID, and (3) a cryptographic signature that proves the owner associated themselves with that alias. This web endpoint is valuable to onboard new SSB users being invited by an internal user.

662 |

Prior art: This endpoint should be in many ways similar to the Telegram https://t.me/example service for the username @example, also capable of redirecting the web visitor to a scheme tg URI tg://resolve?domain=example, which Telegram apps know how to parse and open the target user's profile screen.

663 |

Specification

664 |

This specification does not apply if the privacy mode is Restricted. This web endpoint is available only if the privacy mode is Open or Community.

665 |

If the alias ${alias} is registered at the room ${roomHost} for a certain ${userId}, then the room's HTTP endpoint reserved for the alias SHOULD be the wildcard subdomain URL https://${alias}.${roomHost} but it MAY be https://${roomHost}/${alias}.

666 |

The HTML response then:

667 | 682 |

As an additional endpoint for programmatic purposes, if the query parameter encoding=json is added to the alias endpoint (for illustration: https://${alias}.${roomHost}?encoding=json), then, in successful responses, the JSON body MUST conform to the following schema:

683 |
{
684 |   "$schema": "http://json-schema.org/draft-07/schema#",
685 |   "$id": "https://github.com/ssb-ngi-pointer/rooms2#alias-json-endpoint-success",
686 |   "type": "object",
687 |   "properties": {
688 |     "status": {
689 |       "title": "Response status tag",
690 |       "description": "Indicates the completion status of this response",
691 |       "type": "string",
692 |       "pattern": "^(successful)$"
693 |     },
694 |     "multiserverAddress": {
695 |       "title": "Multiserver address",
696 |       "description": "Should conform to https://github.com/ssbc/multiserver-address",
697 |       "type": "string"
698 |     },
699 |     "roomId": {
700 |       "title": "Room ID",
701 |       "description": "SSB ID for the room server",
702 |       "type": "string"
703 |     },
704 |     "userId": {
705 |       "title": "User ID",
706 |       "description": "SSB ID for the user owning the alias",
707 |       "type": "string"
708 |     },
709 |     "alias": {
710 |       "title": "Alias",
711 |       "description": "A domain 'label' as defined in RFC 1035",
712 |       "type": "string"
713 |     },
714 |     "signature": {
715 |       "title": "Signature",
716 |       "description": "Cryptographic signature covering the roomId, the userId, and the alias",
717 |       "type": "string"
718 |     }
719 |   },
720 |   "required": [
721 |     "status",
722 |     "multiserverAddress",
723 |     "roomId",
724 |     "userId",
725 |     "alias",
726 |     "signature"
727 |   ]
728 | }
729 | 
730 |

In failed responses, the JSON body MUST conform to the following schema:

731 |
{
732 |   "$schema": "http://json-schema.org/draft-07/schema#",
733 |   "$id": "https://github.com/ssb-ngi-pointer/rooms2#alias-json-endpoint-error",
734 |   "type": "object",
735 |   "properties": {
736 |     "status": {
737 |       "title": "Response status tag",
738 |       "description": "Indicates the completion status of this response",
739 |       "type": "string"
740 |     },
741 |     "error": {
742 |       "title": "Response error",
743 |       "description": "Describes the specific error that occurred",
744 |       "type": "string"
745 |     }
746 |   },
747 |   "required": [
748 |     "status",
749 |     "error"
750 |   ]
751 | }
752 | 
753 |

Example

754 |

Suppose the alias is bob, registered for the user ID @yVQxFxzeRQ13DQ813hf8G20U5z5I/nkNDliKeSs/IpU=.ed25519 at the room with host name scuttlebutt.eu. Then the alias endpoint https://bob.scuttlebutt.eu responds with HTML containing the following SSB URI:

755 |

ssb:experimental?action=consume-alias&multiserverAddress=net%3Ascuttlebutt.eu%3A8008~shs%3Azz%2Bn7zuFc4wofIgKeEpXgB%2B%2FXQZB43Xj2rrWyD0QM2M%3D&alias=bob&roomId=%40zz%2Bn7zuFc4wofIgKeEpXgB%2B%2FXQZB43Xj2rrWyD0QM2M%3D.ed25519&userId=%40yVQxFxzeRQ13DQ813hf8G20U5z5I%2FnkNDliKeSs%2FIpU%3D.ed25519&signature=EiEgn%2Fh2lKoaz28ggKBod6havJNKapRKCmXQ%2Ft%2F4KS1gY4T6zPXWhw6kTaglt8vDJZW%2BjJRJvfB4Rryhl0njCg%3D%3D.sig.ed25519

756 |

The JSON endpoint https://bob.scuttlebutt.eu/?encoding=json would respond with the following JSON:

757 |
{
758 |   "status": "successful",
759 |   "multiserverAddress": "net:scuttlebutt.eu:8008~shs:zz+n7zuFc4wofIgKeEpXgB+/XQZB43Xj2rrWyD0QM2M=",
760 |   "roomId": "@zz+n7zuFc4wofIgKeEpXgB+/XQZB43Xj2rrWyD0QM2M=.ed25519",
761 |   "userId": "@yVQxFxzeRQ13DQ813hf8G20U5z5I/nkNDliKeSs/IpU=.ed25519",
762 |   "alias": "bob",
763 |   "signature": "EiEgn/h2lKoaz28ggKBod6havJNKapRKCmXQ/t/4KS1gY4T6zPXWhw6kTaglt8vDJZW+jJRJvfB4Rryhl0njCg==.sig.ed25519"
764 | }
765 | 
766 |

Security considerations

767 |
Malicious web visitor
768 |

A web visitor, either human or bot, could attempt brute force visiting all possible alias endpoints, in order to build a dataset of all SSB IDs and claimed aliases gathered at this room, potentially tracking profiles of these SSB IDs. Malicious web visitors can also attempt to connect with these target IDs as victims, and may use social engineering or impersonation tactics during tunneled authentication.

769 |
Malicious room admin
770 |

The room admin could tamper with the alias database and provide fake information on this web endpoint, e.g. that a certain alias was claimed by a certain users. Although the database signature exists to prevent this type of tampering, it is only verified when performing alias consumption. For web visitors who only want to know which SSB ID corresponds to an alias, and only that, these visitors must trust the room administrator, who could provide inauthentic information.

771 | 776 |

Alias database

777 |

This is a database that stores all aliases that were registered by internal users.

778 |

Example

779 |

The following is a mock up of a key-value store:

780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 |
KeyValue
alice@FlieaFef19uJ6jhHwv2CSkFrDLYKJd/SuIS71A5Y2as=.ed25519 plus signature
bob@25WfId3Vx/gyMAZqCyZzhtW4iPtUVXB/aOMYbq44P4c=.ed25519 plus signature
carla@dRE+jzKo0VWX6JbcSVATyOvFlbjCNwPWNzQLkTGenac=.ed25519 plus signature
daniel@SMMgb4bZAgRgtAPdMw4loQeZL9lQgsRDi+xin0ZDzAg=.ed25519 plus signature
804 |

Specification

805 |

This can be a simple persistent key-value store, such as Leveldb.

806 | 821 |

The signature is applied on the following string: =room-alias-registration:${roomId}:${userId}:${alias}, known as the Alias confirmation, see example (without spaces nor newlines):

822 |
=room-alias-registration:@51w4nYL0k7mRzDGw20KQqCjt35
823 | y8qLiBNtWk3MX7ppo=.ed25519:@FlieaFef19uJ6jhHwv2
824 | CSkFrDLYKJd/SuIS71A5Y2as=.ed25519:alice
825 | 
826 |

where

827 | 832 |

The purpose of a cryptographic signature on the combined roomId & userId & alias is to make sure that the Room admin cannot tamper with the database to delegitimize its contents. This means that each key-value pair is certainly authored by the declared SSB ID, that is, neither the key (the alias) nor the value (the SSB ID) was modified by the Room admin.

833 |

Security considerations

834 |
Malicious room admin
835 |

The room admin can freely read or write to this database, they can create new entries, and so forth. If they modify an entry and thus break the validation of the signatures, other SSB users can detect this when verifying the signatures.

836 |

Thus the admin cannot effectively:

837 | 841 |

But the admin can:

842 | 846 |
Malicious moderator
847 |

Similar considerations as with the room admin, but less powers. The malicious moderator cannot do the actions that the room admin cannot do (otherwise moderators would have more power than admins), but the one thing moderators can do is:

848 | 851 | 856 |

Appendix

857 | 862 |

List of new muxrpc APIs

863 | 877 | 882 |

List of new SSB URIs

883 | 886 | 887 | 888 | 889 | 890 | --------------------------------------------------------------------------------