1# Copyright 2015, 2016 OpenMarket Ltd 2# Copyright 2021 The Matrix.org Foundation C.I.C. 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15import argparse 16from typing import Optional 17 18from synapse.api.constants import RoomCreationPreset 19from synapse.config._base import Config, ConfigError 20from synapse.types import RoomAlias, UserID 21from synapse.util.stringutils import random_string_with_symbols, strtobool 22 23 24class RegistrationConfig(Config): 25 section = "registration" 26 27 def read_config(self, config, **kwargs): 28 self.enable_registration = strtobool( 29 str(config.get("enable_registration", False)) 30 ) 31 if "disable_registration" in config: 32 self.enable_registration = not strtobool( 33 str(config["disable_registration"]) 34 ) 35 36 self.registrations_require_3pid = config.get("registrations_require_3pid", []) 37 self.allowed_local_3pids = config.get("allowed_local_3pids", []) 38 self.enable_3pid_lookup = config.get("enable_3pid_lookup", True) 39 self.registration_requires_token = config.get( 40 "registration_requires_token", False 41 ) 42 self.registration_shared_secret = config.get("registration_shared_secret") 43 44 self.bcrypt_rounds = config.get("bcrypt_rounds", 12) 45 46 account_threepid_delegates = config.get("account_threepid_delegates") or {} 47 self.account_threepid_delegate_email = account_threepid_delegates.get("email") 48 self.account_threepid_delegate_msisdn = account_threepid_delegates.get("msisdn") 49 self.default_identity_server = config.get("default_identity_server") 50 self.allow_guest_access = config.get("allow_guest_access", False) 51 52 if config.get("invite_3pid_guest", False): 53 raise ConfigError("invite_3pid_guest is no longer supported") 54 55 self.auto_join_rooms = config.get("auto_join_rooms", []) 56 for room_alias in self.auto_join_rooms: 57 if not RoomAlias.is_valid(room_alias): 58 raise ConfigError("Invalid auto_join_rooms entry %s" % (room_alias,)) 59 60 # Options for creating auto-join rooms if they do not exist yet. 61 self.autocreate_auto_join_rooms = config.get("autocreate_auto_join_rooms", True) 62 self.autocreate_auto_join_rooms_federated = config.get( 63 "autocreate_auto_join_rooms_federated", True 64 ) 65 self.autocreate_auto_join_room_preset = ( 66 config.get("autocreate_auto_join_room_preset") 67 or RoomCreationPreset.PUBLIC_CHAT 68 ) 69 self.auto_join_room_requires_invite = self.autocreate_auto_join_room_preset in { 70 RoomCreationPreset.PRIVATE_CHAT, 71 RoomCreationPreset.TRUSTED_PRIVATE_CHAT, 72 } 73 74 # Pull the creator/inviter from the configuration, this gets used to 75 # send invites for invite-only rooms. 76 mxid_localpart = config.get("auto_join_mxid_localpart") 77 self.auto_join_user_id = None 78 if mxid_localpart: 79 # Convert the localpart to a full mxid. 80 self.auto_join_user_id = UserID( 81 mxid_localpart, self.root.server.server_name 82 ).to_string() 83 84 if self.autocreate_auto_join_rooms: 85 # Ensure the preset is a known value. 86 if self.autocreate_auto_join_room_preset not in { 87 RoomCreationPreset.PUBLIC_CHAT, 88 RoomCreationPreset.PRIVATE_CHAT, 89 RoomCreationPreset.TRUSTED_PRIVATE_CHAT, 90 }: 91 raise ConfigError("Invalid value for autocreate_auto_join_room_preset") 92 # If the preset requires invitations to be sent, ensure there's a 93 # configured user to send them from. 94 if self.auto_join_room_requires_invite: 95 if not mxid_localpart: 96 raise ConfigError( 97 "The configuration option `auto_join_mxid_localpart` is required if " 98 "`autocreate_auto_join_room_preset` is set to private_chat or trusted_private_chat, such that " 99 "Synapse knows who to send invitations from. Please " 100 "configure `auto_join_mxid_localpart`." 101 ) 102 103 self.auto_join_rooms_for_guests = config.get("auto_join_rooms_for_guests", True) 104 105 self.enable_set_displayname = config.get("enable_set_displayname", True) 106 self.enable_set_avatar_url = config.get("enable_set_avatar_url", True) 107 self.enable_3pid_changes = config.get("enable_3pid_changes", True) 108 109 self.disable_msisdn_registration = config.get( 110 "disable_msisdn_registration", False 111 ) 112 113 session_lifetime = config.get("session_lifetime") 114 if session_lifetime is not None: 115 session_lifetime = self.parse_duration(session_lifetime) 116 self.session_lifetime = session_lifetime 117 118 # The `refreshable_access_token_lifetime` applies for tokens that can be renewed 119 # using a refresh token, as per MSC2918. 120 # If it is `None`, the refresh token mechanism is disabled. 121 refreshable_access_token_lifetime = config.get( 122 "refreshable_access_token_lifetime", 123 "5m", 124 ) 125 if refreshable_access_token_lifetime is not None: 126 refreshable_access_token_lifetime = self.parse_duration( 127 refreshable_access_token_lifetime 128 ) 129 self.refreshable_access_token_lifetime: Optional[ 130 int 131 ] = refreshable_access_token_lifetime 132 133 if ( 134 self.session_lifetime is not None 135 and "refreshable_access_token_lifetime" in config 136 ): 137 if self.session_lifetime < self.refreshable_access_token_lifetime: 138 raise ConfigError( 139 "Both `session_lifetime` and `refreshable_access_token_lifetime` " 140 "configuration options have been set, but `refreshable_access_token_lifetime` " 141 " exceeds `session_lifetime`!" 142 ) 143 144 # The `nonrefreshable_access_token_lifetime` applies for tokens that can NOT be 145 # refreshed using a refresh token. 146 # If it is None, then these tokens last for the entire length of the session, 147 # which is infinite by default. 148 # The intention behind this configuration option is to help with requiring 149 # all clients to use refresh tokens, if the homeserver administrator requires. 150 nonrefreshable_access_token_lifetime = config.get( 151 "nonrefreshable_access_token_lifetime", 152 None, 153 ) 154 if nonrefreshable_access_token_lifetime is not None: 155 nonrefreshable_access_token_lifetime = self.parse_duration( 156 nonrefreshable_access_token_lifetime 157 ) 158 self.nonrefreshable_access_token_lifetime = nonrefreshable_access_token_lifetime 159 160 if ( 161 self.session_lifetime is not None 162 and self.nonrefreshable_access_token_lifetime is not None 163 ): 164 if self.session_lifetime < self.nonrefreshable_access_token_lifetime: 165 raise ConfigError( 166 "Both `session_lifetime` and `nonrefreshable_access_token_lifetime` " 167 "configuration options have been set, but `nonrefreshable_access_token_lifetime` " 168 " exceeds `session_lifetime`!" 169 ) 170 171 refresh_token_lifetime = config.get("refresh_token_lifetime") 172 if refresh_token_lifetime is not None: 173 refresh_token_lifetime = self.parse_duration(refresh_token_lifetime) 174 self.refresh_token_lifetime: Optional[int] = refresh_token_lifetime 175 176 if ( 177 self.session_lifetime is not None 178 and self.refresh_token_lifetime is not None 179 ): 180 if self.session_lifetime < self.refresh_token_lifetime: 181 raise ConfigError( 182 "Both `session_lifetime` and `refresh_token_lifetime` " 183 "configuration options have been set, but `refresh_token_lifetime` " 184 " exceeds `session_lifetime`!" 185 ) 186 187 # The fallback template used for authenticating using a registration token 188 self.registration_token_template = self.read_template("registration_token.html") 189 190 # The success template used during fallback auth. 191 self.fallback_success_template = self.read_template("auth_success.html") 192 193 def generate_config_section(self, generate_secrets=False, **kwargs): 194 if generate_secrets: 195 registration_shared_secret = 'registration_shared_secret: "%s"' % ( 196 random_string_with_symbols(50), 197 ) 198 else: 199 registration_shared_secret = "#registration_shared_secret: <PRIVATE STRING>" 200 201 return ( 202 """\ 203 ## Registration ## 204 # 205 # Registration can be rate-limited using the parameters in the "Ratelimiting" 206 # section of this file. 207 208 # Enable registration for new users. 209 # 210 #enable_registration: false 211 212 # Time that a user's session remains valid for, after they log in. 213 # 214 # Note that this is not currently compatible with guest logins. 215 # 216 # Note also that this is calculated at login time: changes are not applied 217 # retrospectively to users who have already logged in. 218 # 219 # By default, this is infinite. 220 # 221 #session_lifetime: 24h 222 223 # Time that an access token remains valid for, if the session is 224 # using refresh tokens. 225 # For more information about refresh tokens, please see the manual. 226 # Note that this only applies to clients which advertise support for 227 # refresh tokens. 228 # 229 # Note also that this is calculated at login time and refresh time: 230 # changes are not applied to existing sessions until they are refreshed. 231 # 232 # By default, this is 5 minutes. 233 # 234 #refreshable_access_token_lifetime: 5m 235 236 # Time that a refresh token remains valid for (provided that it is not 237 # exchanged for another one first). 238 # This option can be used to automatically log-out inactive sessions. 239 # Please see the manual for more information. 240 # 241 # Note also that this is calculated at login time and refresh time: 242 # changes are not applied to existing sessions until they are refreshed. 243 # 244 # By default, this is infinite. 245 # 246 #refresh_token_lifetime: 24h 247 248 # Time that an access token remains valid for, if the session is NOT 249 # using refresh tokens. 250 # Please note that not all clients support refresh tokens, so setting 251 # this to a short value may be inconvenient for some users who will 252 # then be logged out frequently. 253 # 254 # Note also that this is calculated at login time: changes are not applied 255 # retrospectively to existing sessions for users that have already logged in. 256 # 257 # By default, this is infinite. 258 # 259 #nonrefreshable_access_token_lifetime: 24h 260 261 # The user must provide all of the below types of 3PID when registering. 262 # 263 #registrations_require_3pid: 264 # - email 265 # - msisdn 266 267 # Explicitly disable asking for MSISDNs from the registration 268 # flow (overrides registrations_require_3pid if MSISDNs are set as required) 269 # 270 #disable_msisdn_registration: true 271 272 # Mandate that users are only allowed to associate certain formats of 273 # 3PIDs with accounts on this server. 274 # 275 #allowed_local_3pids: 276 # - medium: email 277 # pattern: '^[^@]+@matrix\\.org$' 278 # - medium: email 279 # pattern: '^[^@]+@vector\\.im$' 280 # - medium: msisdn 281 # pattern: '\\+44' 282 283 # Enable 3PIDs lookup requests to identity servers from this server. 284 # 285 #enable_3pid_lookup: true 286 287 # Require users to submit a token during registration. 288 # Tokens can be managed using the admin API: 289 # https://matrix-org.github.io/synapse/latest/usage/administration/admin_api/registration_tokens.html 290 # Note that `enable_registration` must be set to `true`. 291 # Disabling this option will not delete any tokens previously generated. 292 # Defaults to false. Uncomment the following to require tokens: 293 # 294 #registration_requires_token: true 295 296 # If set, allows registration of standard or admin accounts by anyone who 297 # has the shared secret, even if registration is otherwise disabled. 298 # 299 %(registration_shared_secret)s 300 301 # Set the number of bcrypt rounds used to generate password hash. 302 # Larger numbers increase the work factor needed to generate the hash. 303 # The default number is 12 (which equates to 2^12 rounds). 304 # N.B. that increasing this will exponentially increase the time required 305 # to register or login - e.g. 24 => 2^24 rounds which will take >20 mins. 306 # 307 #bcrypt_rounds: 12 308 309 # Allows users to register as guests without a password/email/etc, and 310 # participate in rooms hosted on this server which have been made 311 # accessible to anonymous users. 312 # 313 #allow_guest_access: false 314 315 # The identity server which we suggest that clients should use when users log 316 # in on this server. 317 # 318 # (By default, no suggestion is made, so it is left up to the client. 319 # This setting is ignored unless public_baseurl is also explicitly set.) 320 # 321 #default_identity_server: https://matrix.org 322 323 # Handle threepid (email/phone etc) registration and password resets through a set of 324 # *trusted* identity servers. Note that this allows the configured identity server to 325 # reset passwords for accounts! 326 # 327 # Be aware that if `email` is not set, and SMTP options have not been 328 # configured in the email config block, registration and user password resets via 329 # email will be globally disabled. 330 # 331 # Additionally, if `msisdn` is not set, registration and password resets via msisdn 332 # will be disabled regardless, and users will not be able to associate an msisdn 333 # identifier to their account. This is due to Synapse currently not supporting 334 # any method of sending SMS messages on its own. 335 # 336 # To enable using an identity server for operations regarding a particular third-party 337 # identifier type, set the value to the URL of that identity server as shown in the 338 # examples below. 339 # 340 # Servers handling the these requests must answer the `/requestToken` endpoints defined 341 # by the Matrix Identity Service API specification: 342 # https://matrix.org/docs/spec/identity_service/latest 343 # 344 account_threepid_delegates: 345 #email: https://example.com # Delegate email sending to example.com 346 #msisdn: http://localhost:8090 # Delegate SMS sending to this local process 347 348 # Whether users are allowed to change their displayname after it has 349 # been initially set. Useful when provisioning users based on the 350 # contents of a third-party directory. 351 # 352 # Does not apply to server administrators. Defaults to 'true' 353 # 354 #enable_set_displayname: false 355 356 # Whether users are allowed to change their avatar after it has been 357 # initially set. Useful when provisioning users based on the contents 358 # of a third-party directory. 359 # 360 # Does not apply to server administrators. Defaults to 'true' 361 # 362 #enable_set_avatar_url: false 363 364 # Whether users can change the 3PIDs associated with their accounts 365 # (email address and msisdn). 366 # 367 # Defaults to 'true' 368 # 369 #enable_3pid_changes: false 370 371 # Users who register on this homeserver will automatically be joined 372 # to these rooms. 373 # 374 # By default, any room aliases included in this list will be created 375 # as a publicly joinable room when the first user registers for the 376 # homeserver. This behaviour can be customised with the settings below. 377 # If the room already exists, make certain it is a publicly joinable 378 # room. The join rule of the room must be set to 'public'. 379 # 380 #auto_join_rooms: 381 # - "#example:example.com" 382 383 # Where auto_join_rooms are specified, setting this flag ensures that the 384 # the rooms exist by creating them when the first user on the 385 # homeserver registers. 386 # 387 # By default the auto-created rooms are publicly joinable from any federated 388 # server. Use the autocreate_auto_join_rooms_federated and 389 # autocreate_auto_join_room_preset settings below to customise this behaviour. 390 # 391 # Setting to false means that if the rooms are not manually created, 392 # users cannot be auto-joined since they do not exist. 393 # 394 # Defaults to true. Uncomment the following line to disable automatically 395 # creating auto-join rooms. 396 # 397 #autocreate_auto_join_rooms: false 398 399 # Whether the auto_join_rooms that are auto-created are available via 400 # federation. Only has an effect if autocreate_auto_join_rooms is true. 401 # 402 # Note that whether a room is federated cannot be modified after 403 # creation. 404 # 405 # Defaults to true: the room will be joinable from other servers. 406 # Uncomment the following to prevent users from other homeservers from 407 # joining these rooms. 408 # 409 #autocreate_auto_join_rooms_federated: false 410 411 # The room preset to use when auto-creating one of auto_join_rooms. Only has an 412 # effect if autocreate_auto_join_rooms is true. 413 # 414 # This can be one of "public_chat", "private_chat", or "trusted_private_chat". 415 # If a value of "private_chat" or "trusted_private_chat" is used then 416 # auto_join_mxid_localpart must also be configured. 417 # 418 # Defaults to "public_chat", meaning that the room is joinable by anyone, including 419 # federated servers if autocreate_auto_join_rooms_federated is true (the default). 420 # Uncomment the following to require an invitation to join these rooms. 421 # 422 #autocreate_auto_join_room_preset: private_chat 423 424 # The local part of the user id which is used to create auto_join_rooms if 425 # autocreate_auto_join_rooms is true. If this is not provided then the 426 # initial user account that registers will be used to create the rooms. 427 # 428 # The user id is also used to invite new users to any auto-join rooms which 429 # are set to invite-only. 430 # 431 # It *must* be configured if autocreate_auto_join_room_preset is set to 432 # "private_chat" or "trusted_private_chat". 433 # 434 # Note that this must be specified in order for new users to be correctly 435 # invited to any auto-join rooms which have been set to invite-only (either 436 # at the time of creation or subsequently). 437 # 438 # Note that, if the room already exists, this user must be joined and 439 # have the appropriate permissions to invite new members. 440 # 441 #auto_join_mxid_localpart: system 442 443 # When auto_join_rooms is specified, setting this flag to false prevents 444 # guest accounts from being automatically joined to the rooms. 445 # 446 # Defaults to true. 447 # 448 #auto_join_rooms_for_guests: false 449 """ 450 % locals() 451 ) 452 453 @staticmethod 454 def add_arguments(parser: argparse.ArgumentParser) -> None: 455 reg_group = parser.add_argument_group("registration") 456 reg_group.add_argument( 457 "--enable-registration", 458 action="store_true", 459 default=None, 460 help="Enable registration for new users.", 461 ) 462 463 def read_arguments(self, args: argparse.Namespace) -> None: 464 if args.enable_registration is not None: 465 self.enable_registration = strtobool(str(args.enable_registration)) 466