register.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2015 - 2016 OpenMarket Ltd
  3. # Copyright 2017 Vector Creations Ltd
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. from twisted.internet import defer
  17. import synapse
  18. import synapse.types
  19. from synapse.api.auth import get_access_token_from_request, has_access_token
  20. from synapse.api.constants import LoginType
  21. from synapse.types import RoomID, RoomAlias
  22. from synapse.api.errors import SynapseError, Codes, UnrecognizedRequestError
  23. from synapse.http.servlet import (
  24. RestServlet, parse_json_object_from_request, assert_params_in_request, parse_string
  25. )
  26. from synapse.util.msisdn import phone_number_to_msisdn
  27. from synapse.util.threepids import check_3pid_allowed
  28. from ._base import client_v2_patterns, interactive_auth_handler
  29. import logging
  30. import hmac
  31. from hashlib import sha1
  32. from synapse.util.async import run_on_reactor
  33. from synapse.util.ratelimitutils import FederationRateLimiter
  34. # We ought to be using hmac.compare_digest() but on older pythons it doesn't
  35. # exist. It's a _really minor_ security flaw to use plain string comparison
  36. # because the timing attack is so obscured by all the other code here it's
  37. # unlikely to make much difference
  38. if hasattr(hmac, "compare_digest"):
  39. compare_digest = hmac.compare_digest
  40. else:
  41. def compare_digest(a, b):
  42. return a == b
  43. logger = logging.getLogger(__name__)
  44. class EmailRegisterRequestTokenRestServlet(RestServlet):
  45. PATTERNS = client_v2_patterns("/register/email/requestToken$")
  46. def __init__(self, hs):
  47. """
  48. Args:
  49. hs (synapse.server.HomeServer): server
  50. """
  51. super(EmailRegisterRequestTokenRestServlet, self).__init__()
  52. self.hs = hs
  53. self.identity_handler = hs.get_handlers().identity_handler
  54. @defer.inlineCallbacks
  55. def on_POST(self, request):
  56. body = parse_json_object_from_request(request)
  57. assert_params_in_request(body, [
  58. 'id_server', 'client_secret', 'email', 'send_attempt'
  59. ])
  60. if not check_3pid_allowed(self.hs, "email", body['email']):
  61. raise SynapseError(
  62. 403, "Third party identifier is not allowed", Codes.THREEPID_DENIED,
  63. )
  64. existingUid = yield self.hs.get_datastore().get_user_id_by_threepid(
  65. 'email', body['email']
  66. )
  67. if existingUid is not None:
  68. raise SynapseError(400, "Email is already in use", Codes.THREEPID_IN_USE)
  69. ret = yield self.identity_handler.requestEmailToken(**body)
  70. defer.returnValue((200, ret))
  71. class MsisdnRegisterRequestTokenRestServlet(RestServlet):
  72. PATTERNS = client_v2_patterns("/register/msisdn/requestToken$")
  73. def __init__(self, hs):
  74. """
  75. Args:
  76. hs (synapse.server.HomeServer): server
  77. """
  78. super(MsisdnRegisterRequestTokenRestServlet, self).__init__()
  79. self.hs = hs
  80. self.identity_handler = hs.get_handlers().identity_handler
  81. @defer.inlineCallbacks
  82. def on_POST(self, request):
  83. body = parse_json_object_from_request(request)
  84. assert_params_in_request(body, [
  85. 'id_server', 'client_secret',
  86. 'country', 'phone_number',
  87. 'send_attempt',
  88. ])
  89. msisdn = phone_number_to_msisdn(body['country'], body['phone_number'])
  90. if not check_3pid_allowed(self.hs, "msisdn", msisdn):
  91. raise SynapseError(
  92. 403, "Third party identifier is not allowed", Codes.THREEPID_DENIED,
  93. )
  94. existingUid = yield self.hs.get_datastore().get_user_id_by_threepid(
  95. 'msisdn', msisdn
  96. )
  97. if existingUid is not None:
  98. raise SynapseError(
  99. 400, "Phone number is already in use", Codes.THREEPID_IN_USE
  100. )
  101. ret = yield self.identity_handler.requestMsisdnToken(**body)
  102. defer.returnValue((200, ret))
  103. class UsernameAvailabilityRestServlet(RestServlet):
  104. PATTERNS = client_v2_patterns("/register/available")
  105. def __init__(self, hs):
  106. """
  107. Args:
  108. hs (synapse.server.HomeServer): server
  109. """
  110. super(UsernameAvailabilityRestServlet, self).__init__()
  111. self.hs = hs
  112. self.registration_handler = hs.get_handlers().registration_handler
  113. self.ratelimiter = FederationRateLimiter(
  114. hs.get_clock(),
  115. # Time window of 2s
  116. window_size=2000,
  117. # Artificially delay requests if rate > sleep_limit/window_size
  118. sleep_limit=1,
  119. # Amount of artificial delay to apply
  120. sleep_msec=1000,
  121. # Error with 429 if more than reject_limit requests are queued
  122. reject_limit=1,
  123. # Allow 1 request at a time
  124. concurrent_requests=1,
  125. )
  126. @defer.inlineCallbacks
  127. def on_GET(self, request):
  128. ip = self.hs.get_ip_from_request(request)
  129. with self.ratelimiter.ratelimit(ip) as wait_deferred:
  130. yield wait_deferred
  131. username = parse_string(request, "username", required=True)
  132. yield self.registration_handler.check_username(username)
  133. defer.returnValue((200, {"available": True}))
  134. class RegisterRestServlet(RestServlet):
  135. PATTERNS = client_v2_patterns("/register$")
  136. def __init__(self, hs):
  137. """
  138. Args:
  139. hs (synapse.server.HomeServer): server
  140. """
  141. super(RegisterRestServlet, self).__init__()
  142. self.hs = hs
  143. self.auth = hs.get_auth()
  144. self.store = hs.get_datastore()
  145. self.auth_handler = hs.get_auth_handler()
  146. self.registration_handler = hs.get_handlers().registration_handler
  147. self.identity_handler = hs.get_handlers().identity_handler
  148. self.room_member_handler = hs.get_room_member_handler()
  149. self.device_handler = hs.get_device_handler()
  150. self.macaroon_gen = hs.get_macaroon_generator()
  151. @interactive_auth_handler
  152. @defer.inlineCallbacks
  153. def on_POST(self, request):
  154. yield run_on_reactor()
  155. body = parse_json_object_from_request(request)
  156. kind = "user"
  157. if "kind" in request.args:
  158. kind = request.args["kind"][0]
  159. if kind == "guest":
  160. ret = yield self._do_guest_registration(body)
  161. defer.returnValue(ret)
  162. return
  163. elif kind != "user":
  164. raise UnrecognizedRequestError(
  165. "Do not understand membership kind: %s" % (kind,)
  166. )
  167. # we do basic sanity checks here because the auth layer will store these
  168. # in sessions. Pull out the username/password provided to us.
  169. desired_password = None
  170. if 'password' in body:
  171. if (not isinstance(body['password'], basestring) or
  172. len(body['password']) > 512):
  173. raise SynapseError(400, "Invalid password")
  174. desired_password = body["password"]
  175. desired_username = None
  176. if 'username' in body:
  177. if (not isinstance(body['username'], basestring) or
  178. len(body['username']) > 512):
  179. raise SynapseError(400, "Invalid username")
  180. desired_username = body['username']
  181. appservice = None
  182. if has_access_token(request):
  183. appservice = yield self.auth.get_appservice_by_req(request)
  184. # fork off as soon as possible for ASes and shared secret auth which
  185. # have completely different registration flows to normal users
  186. # == Application Service Registration ==
  187. if appservice:
  188. # Set the desired user according to the AS API (which uses the
  189. # 'user' key not 'username'). Since this is a new addition, we'll
  190. # fallback to 'username' if they gave one.
  191. desired_username = body.get("user", desired_username)
  192. # XXX we should check that desired_username is valid. Currently
  193. # we give appservices carte blanche for any insanity in mxids,
  194. # because the IRC bridges rely on being able to register stupid
  195. # IDs.
  196. access_token = get_access_token_from_request(request)
  197. if isinstance(desired_username, basestring):
  198. result = yield self._do_appservice_registration(
  199. desired_username, access_token, body
  200. )
  201. defer.returnValue((200, result)) # we throw for non 200 responses
  202. return
  203. # for either shared secret or regular registration, downcase the
  204. # provided username before attempting to register it. This should mean
  205. # that people who try to register with upper-case in their usernames
  206. # don't get a nasty surprise. (Note that we treat username
  207. # case-insenstively in login, so they are free to carry on imagining
  208. # that their username is CrAzYh4cKeR if that keeps them happy)
  209. if desired_username is not None:
  210. desired_username = desired_username.lower()
  211. # == Shared Secret Registration == (e.g. create new user scripts)
  212. if 'mac' in body:
  213. # FIXME: Should we really be determining if this is shared secret
  214. # auth based purely on the 'mac' key?
  215. result = yield self._do_shared_secret_registration(
  216. desired_username, desired_password, body
  217. )
  218. defer.returnValue((200, result)) # we throw for non 200 responses
  219. return
  220. # == Normal User Registration == (everyone else)
  221. if not self.hs.config.enable_registration:
  222. raise SynapseError(403, "Registration has been disabled")
  223. guest_access_token = body.get("guest_access_token", None)
  224. if (
  225. 'initial_device_display_name' in body and
  226. 'password' not in body
  227. ):
  228. # ignore 'initial_device_display_name' if sent without
  229. # a password to work around a client bug where it sent
  230. # the 'initial_device_display_name' param alone, wiping out
  231. # the original registration params
  232. logger.warn("Ignoring initial_device_display_name without password")
  233. del body['initial_device_display_name']
  234. session_id = self.auth_handler.get_session_id(body)
  235. registered_user_id = None
  236. if session_id:
  237. # if we get a registered user id out of here, it means we previously
  238. # registered a user for this session, so we could just return the
  239. # user here. We carry on and go through the auth checks though,
  240. # for paranoia.
  241. registered_user_id = self.auth_handler.get_session_data(
  242. session_id, "registered_user_id", None
  243. )
  244. if desired_username is not None:
  245. yield self.registration_handler.check_username(
  246. desired_username,
  247. guest_access_token=guest_access_token,
  248. assigned_user_id=registered_user_id,
  249. )
  250. # Only give msisdn flows if the x_show_msisdn flag is given:
  251. # this is a hack to work around the fact that clients were shipped
  252. # that use fallback registration if they see any flows that they don't
  253. # recognise, which means we break registration for these clients if we
  254. # advertise msisdn flows. Once usage of Riot iOS <=0.3.9 and Riot
  255. # Android <=0.6.9 have fallen below an acceptable threshold, this
  256. # parameter should go away and we should always advertise msisdn flows.
  257. show_msisdn = False
  258. if 'x_show_msisdn' in body and body['x_show_msisdn']:
  259. show_msisdn = True
  260. # FIXME: need a better error than "no auth flow found" for scenarios
  261. # where we required 3PID for registration but the user didn't give one
  262. require_email = 'email' in self.hs.config.registrations_require_3pid
  263. require_msisdn = 'msisdn' in self.hs.config.registrations_require_3pid
  264. flows = []
  265. if self.hs.config.enable_registration_captcha:
  266. # only support 3PIDless registration if no 3PIDs are required
  267. if not require_email and not require_msisdn:
  268. flows.extend([[LoginType.RECAPTCHA]])
  269. # only support the email-only flow if we don't require MSISDN 3PIDs
  270. if not require_msisdn:
  271. flows.extend([[LoginType.EMAIL_IDENTITY, LoginType.RECAPTCHA]])
  272. if show_msisdn:
  273. # only support the MSISDN-only flow if we don't require email 3PIDs
  274. if not require_email:
  275. flows.extend([[LoginType.MSISDN, LoginType.RECAPTCHA]])
  276. # always let users provide both MSISDN & email
  277. flows.extend([
  278. [LoginType.MSISDN, LoginType.EMAIL_IDENTITY, LoginType.RECAPTCHA],
  279. ])
  280. else:
  281. # only support 3PIDless registration if no 3PIDs are required
  282. if not require_email and not require_msisdn:
  283. flows.extend([[LoginType.DUMMY]])
  284. # only support the email-only flow if we don't require MSISDN 3PIDs
  285. if not require_msisdn:
  286. flows.extend([[LoginType.EMAIL_IDENTITY]])
  287. if show_msisdn:
  288. # only support the MSISDN-only flow if we don't require email 3PIDs
  289. if not require_email or require_msisdn:
  290. flows.extend([[LoginType.MSISDN]])
  291. # always let users provide both MSISDN & email
  292. flows.extend([
  293. [LoginType.MSISDN, LoginType.EMAIL_IDENTITY]
  294. ])
  295. auth_result, params, session_id = yield self.auth_handler.check_auth(
  296. flows, body, self.hs.get_ip_from_request(request)
  297. )
  298. # Check that we're not trying to register a denied 3pid.
  299. #
  300. # the user-facing checks will probably already have happened in
  301. # /register/email/requestToken when we requested a 3pid, but that's not
  302. # guaranteed.
  303. if auth_result:
  304. for login_type in [LoginType.EMAIL_IDENTITY, LoginType.MSISDN]:
  305. if login_type in auth_result:
  306. medium = auth_result[login_type]['medium']
  307. address = auth_result[login_type]['address']
  308. if not check_3pid_allowed(self.hs, medium, address):
  309. raise SynapseError(
  310. 403, "Third party identifier is not allowed",
  311. Codes.THREEPID_DENIED,
  312. )
  313. if registered_user_id is not None:
  314. logger.info(
  315. "Already registered user ID %r for this session",
  316. registered_user_id
  317. )
  318. # don't re-register the threepids
  319. add_email = False
  320. add_msisdn = False
  321. else:
  322. # NB: This may be from the auth handler and NOT from the POST
  323. if 'password' not in params:
  324. raise SynapseError(400, "Missing password.",
  325. Codes.MISSING_PARAM)
  326. desired_username = params.get("username", None)
  327. new_password = params.get("password", None)
  328. guest_access_token = params.get("guest_access_token", None)
  329. if desired_username is not None:
  330. desired_username = desired_username.lower()
  331. (registered_user_id, _) = yield self.registration_handler.register(
  332. localpart=desired_username,
  333. password=new_password,
  334. guest_access_token=guest_access_token,
  335. generate_token=False,
  336. )
  337. # auto-join the user to any rooms we're supposed to dump them into
  338. fake_requester = synapse.types.create_requester(registered_user_id)
  339. for r in self.hs.config.auto_join_rooms:
  340. try:
  341. yield self._join_user_to_room(fake_requester, r)
  342. except Exception as e:
  343. logger.error("Failed to join new user to %r: %r", r, e)
  344. # remember that we've now registered that user account, and with
  345. # what user ID (since the user may not have specified)
  346. self.auth_handler.set_session_data(
  347. session_id, "registered_user_id", registered_user_id
  348. )
  349. add_email = True
  350. add_msisdn = True
  351. return_dict = yield self._create_registration_details(
  352. registered_user_id, params
  353. )
  354. if add_email and auth_result and LoginType.EMAIL_IDENTITY in auth_result:
  355. threepid = auth_result[LoginType.EMAIL_IDENTITY]
  356. yield self._register_email_threepid(
  357. registered_user_id, threepid, return_dict["access_token"],
  358. params.get("bind_email")
  359. )
  360. if add_msisdn and auth_result and LoginType.MSISDN in auth_result:
  361. threepid = auth_result[LoginType.MSISDN]
  362. yield self._register_msisdn_threepid(
  363. registered_user_id, threepid, return_dict["access_token"],
  364. params.get("bind_msisdn")
  365. )
  366. defer.returnValue((200, return_dict))
  367. def on_OPTIONS(self, _):
  368. return 200, {}
  369. @defer.inlineCallbacks
  370. def _join_user_to_room(self, requester, room_identifier):
  371. room_id = None
  372. if RoomID.is_valid(room_identifier):
  373. room_id = room_identifier
  374. elif RoomAlias.is_valid(room_identifier):
  375. room_alias = RoomAlias.from_string(room_identifier)
  376. room_id, remote_room_hosts = (
  377. yield self.room_member_handler.lookup_room_alias(room_alias)
  378. )
  379. room_id = room_id.to_string()
  380. else:
  381. raise SynapseError(400, "%s was not legal room ID or room alias" % (
  382. room_identifier,
  383. ))
  384. yield self.room_member_handler.update_membership(
  385. requester=requester,
  386. target=requester.user,
  387. room_id=room_id,
  388. action="join",
  389. )
  390. @defer.inlineCallbacks
  391. def _do_appservice_registration(self, username, as_token, body):
  392. user_id = yield self.registration_handler.appservice_register(
  393. username, as_token
  394. )
  395. defer.returnValue((yield self._create_registration_details(user_id, body)))
  396. @defer.inlineCallbacks
  397. def _do_shared_secret_registration(self, username, password, body):
  398. if not self.hs.config.registration_shared_secret:
  399. raise SynapseError(400, "Shared secret registration is not enabled")
  400. if not username:
  401. raise SynapseError(
  402. 400, "username must be specified", errcode=Codes.BAD_JSON,
  403. )
  404. # use the username from the original request rather than the
  405. # downcased one in `username` for the mac calculation
  406. user = body["username"].encode("utf-8")
  407. # str() because otherwise hmac complains that 'unicode' does not
  408. # have the buffer interface
  409. got_mac = str(body["mac"])
  410. # FIXME this is different to the /v1/register endpoint, which
  411. # includes the password and admin flag in the hashed text. Why are
  412. # these different?
  413. want_mac = hmac.new(
  414. key=self.hs.config.registration_shared_secret,
  415. msg=user,
  416. digestmod=sha1,
  417. ).hexdigest()
  418. if not compare_digest(want_mac, got_mac):
  419. raise SynapseError(
  420. 403, "HMAC incorrect",
  421. )
  422. (user_id, _) = yield self.registration_handler.register(
  423. localpart=username, password=password, generate_token=False,
  424. )
  425. result = yield self._create_registration_details(user_id, body)
  426. defer.returnValue(result)
  427. @defer.inlineCallbacks
  428. def _register_email_threepid(self, user_id, threepid, token, bind_email):
  429. """Add an email address as a 3pid identifier
  430. Also adds an email pusher for the email address, if configured in the
  431. HS config
  432. Also optionally binds emails to the given user_id on the identity server
  433. Args:
  434. user_id (str): id of user
  435. threepid (object): m.login.email.identity auth response
  436. token (str): access_token for the user
  437. bind_email (bool): true if the client requested the email to be
  438. bound at the identity server
  439. Returns:
  440. defer.Deferred:
  441. """
  442. reqd = ('medium', 'address', 'validated_at')
  443. if any(x not in threepid for x in reqd):
  444. # This will only happen if the ID server returns a malformed response
  445. logger.info("Can't add incomplete 3pid")
  446. return
  447. yield self.auth_handler.add_threepid(
  448. user_id,
  449. threepid['medium'],
  450. threepid['address'],
  451. threepid['validated_at'],
  452. )
  453. # And we add an email pusher for them by default, but only
  454. # if email notifications are enabled (so people don't start
  455. # getting mail spam where they weren't before if email
  456. # notifs are set up on a home server)
  457. if (self.hs.config.email_enable_notifs and
  458. self.hs.config.email_notif_for_new_users):
  459. # Pull the ID of the access token back out of the db
  460. # It would really make more sense for this to be passed
  461. # up when the access token is saved, but that's quite an
  462. # invasive change I'd rather do separately.
  463. user_tuple = yield self.store.get_user_by_access_token(
  464. token
  465. )
  466. token_id = user_tuple["token_id"]
  467. yield self.hs.get_pusherpool().add_pusher(
  468. user_id=user_id,
  469. access_token=token_id,
  470. kind="email",
  471. app_id="m.email",
  472. app_display_name="Email Notifications",
  473. device_display_name=threepid["address"],
  474. pushkey=threepid["address"],
  475. lang=None, # We don't know a user's language here
  476. data={},
  477. )
  478. if bind_email:
  479. logger.info("bind_email specified: binding")
  480. logger.debug("Binding emails %s to %s" % (
  481. threepid, user_id
  482. ))
  483. yield self.identity_handler.bind_threepid(
  484. threepid['threepid_creds'], user_id
  485. )
  486. else:
  487. logger.info("bind_email not specified: not binding email")
  488. @defer.inlineCallbacks
  489. def _register_msisdn_threepid(self, user_id, threepid, token, bind_msisdn):
  490. """Add a phone number as a 3pid identifier
  491. Also optionally binds msisdn to the given user_id on the identity server
  492. Args:
  493. user_id (str): id of user
  494. threepid (object): m.login.msisdn auth response
  495. token (str): access_token for the user
  496. bind_email (bool): true if the client requested the email to be
  497. bound at the identity server
  498. Returns:
  499. defer.Deferred:
  500. """
  501. reqd = ('medium', 'address', 'validated_at')
  502. if any(x not in threepid for x in reqd):
  503. # This will only happen if the ID server returns a malformed response
  504. logger.info("Can't add incomplete 3pid")
  505. defer.returnValue()
  506. yield self.auth_handler.add_threepid(
  507. user_id,
  508. threepid['medium'],
  509. threepid['address'],
  510. threepid['validated_at'],
  511. )
  512. if bind_msisdn:
  513. logger.info("bind_msisdn specified: binding")
  514. logger.debug("Binding msisdn %s to %s", threepid, user_id)
  515. yield self.identity_handler.bind_threepid(
  516. threepid['threepid_creds'], user_id
  517. )
  518. else:
  519. logger.info("bind_msisdn not specified: not binding msisdn")
  520. @defer.inlineCallbacks
  521. def _create_registration_details(self, user_id, params):
  522. """Complete registration of newly-registered user
  523. Allocates device_id if one was not given; also creates access_token.
  524. Args:
  525. (str) user_id: full canonical @user:id
  526. (object) params: registration parameters, from which we pull
  527. device_id, initial_device_name and inhibit_login
  528. Returns:
  529. defer.Deferred: (object) dictionary for response from /register
  530. """
  531. result = {
  532. "user_id": user_id,
  533. "home_server": self.hs.hostname,
  534. }
  535. if not params.get("inhibit_login", False):
  536. device_id = yield self._register_device(user_id, params)
  537. access_token = (
  538. yield self.auth_handler.get_access_token_for_user_id(
  539. user_id, device_id=device_id,
  540. )
  541. )
  542. result.update({
  543. "access_token": access_token,
  544. "device_id": device_id,
  545. })
  546. defer.returnValue(result)
  547. def _register_device(self, user_id, params):
  548. """Register a device for a user.
  549. This is called after the user's credentials have been validated, but
  550. before the access token has been issued.
  551. Args:
  552. (str) user_id: full canonical @user:id
  553. (object) params: registration parameters, from which we pull
  554. device_id and initial_device_name
  555. Returns:
  556. defer.Deferred: (str) device_id
  557. """
  558. # register the user's device
  559. device_id = params.get("device_id")
  560. initial_display_name = params.get("initial_device_display_name")
  561. return self.device_handler.check_device_registered(
  562. user_id, device_id, initial_display_name
  563. )
  564. @defer.inlineCallbacks
  565. def _do_guest_registration(self, params):
  566. if not self.hs.config.allow_guest_access:
  567. defer.returnValue((403, "Guest access is disabled"))
  568. user_id, _ = yield self.registration_handler.register(
  569. generate_token=False,
  570. make_guest=True
  571. )
  572. # we don't allow guests to specify their own device_id, because
  573. # we have nowhere to store it.
  574. device_id = synapse.api.auth.GUEST_DEVICE_ID
  575. initial_display_name = params.get("initial_device_display_name")
  576. yield self.device_handler.check_device_registered(
  577. user_id, device_id, initial_display_name
  578. )
  579. access_token = self.macaroon_gen.generate_access_token(
  580. user_id, ["guest = true"]
  581. )
  582. defer.returnValue((200, {
  583. "user_id": user_id,
  584. "device_id": device_id,
  585. "access_token": access_token,
  586. "home_server": self.hs.hostname,
  587. }))
  588. def register_servlets(hs, http_server):
  589. EmailRegisterRequestTokenRestServlet(hs).register(http_server)
  590. MsisdnRegisterRequestTokenRestServlet(hs).register(http_server)
  591. UsernameAvailabilityRestServlet(hs).register(http_server)
  592. RegisterRestServlet(hs).register(http_server)