From ce3e583d94c9fb3ee98365e07f4695d1b9451434 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 14 Feb 2017 15:05:55 +0000 Subject: WIP support for msisdn 3pid proxy methods --- synapse/handlers/auth.py | 30 +++++++++++++++++++++++++----- synapse/handlers/identity.py | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 6 deletions(-) (limited to 'synapse/handlers') diff --git a/synapse/handlers/auth.py b/synapse/handlers/auth.py index fffba34383..448bc0b31f 100644 --- a/synapse/handlers/auth.py +++ b/synapse/handlers/auth.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # Copyright 2014 - 2016 OpenMarket Ltd +# Copyright 2017 Vector Creations Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -47,6 +48,7 @@ class AuthHandler(BaseHandler): LoginType.PASSWORD: self._check_password_auth, LoginType.RECAPTCHA: self._check_recaptcha, LoginType.EMAIL_IDENTITY: self._check_email_identity, + LoginType.MSISDN: self._check_msisdn, LoginType.DUMMY: self._check_dummy_auth, } self.bcrypt_rounds = hs.config.bcrypt_rounds @@ -309,12 +311,26 @@ class AuthHandler(BaseHandler): @defer.inlineCallbacks def _check_email_identity(self, authdict, _): + defer.returnValue(self._check_threepid('email', authdict)) + + @defer.inlineCallbacks + def _check_msisdn(self, authdict, _): + defer.returnValue(self._check_threepid('msisdn', authdict)) + + @defer.inlineCallbacks + def _check_dummy_auth(self, authdict, _): + yield run_on_reactor() + defer.returnValue(True) + + @defer.inlineCallbacks + def _check_threepid(self, medium, authdict, ): yield run_on_reactor() if 'threepid_creds' not in authdict: raise LoginError(400, "Missing threepid_creds", Codes.MISSING_PARAM) threepid_creds = authdict['threepid_creds'] + identity_handler = self.hs.get_handlers().identity_handler logger.info("Getting validated threepid. threepidcreds: %r" % (threepid_creds,)) @@ -323,15 +339,19 @@ class AuthHandler(BaseHandler): if not threepid: raise LoginError(401, "", errcode=Codes.UNAUTHORIZED) + if threepid['medium'] != medium: + raise LoginError( + 401, + "Expecting threepid of type '%s', got '%s'" % ( + medium, threepid['medium'], + ), + errcode=Codes.UNAUTHORIZED + ) + threepid['threepid_creds'] = authdict['threepid_creds'] defer.returnValue(threepid) - @defer.inlineCallbacks - def _check_dummy_auth(self, authdict, _): - yield run_on_reactor() - defer.returnValue(True) - def _get_params_recaptcha(self): return {"public_key": self.hs.config.recaptcha_public_key} diff --git a/synapse/handlers/identity.py b/synapse/handlers/identity.py index 559e5d5a71..6a53c5eb47 100644 --- a/synapse/handlers/identity.py +++ b/synapse/handlers/identity.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # Copyright 2015, 2016 OpenMarket Ltd +# Copyright 2017 Vector Creations Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -150,7 +151,7 @@ class IdentityHandler(BaseHandler): params.update(kwargs) try: - data = yield self.http_client.post_urlencoded_get_json( + data = yield self.http_client.post_json_get_json( "https://%s%s" % ( id_server, "/_matrix/identity/api/v1/validate/email/requestToken" @@ -161,3 +162,37 @@ class IdentityHandler(BaseHandler): except CodeMessageException as e: logger.info("Proxied requestToken failed: %r", e) raise e + + @defer.inlineCallbacks + def requestMsisdnToken( + self, id_server, country, phone_number, + client_secret, send_attempt, **kwargs + ): + yield run_on_reactor() + + if not self._should_trust_id_server(id_server): + raise SynapseError( + 400, "Untrusted ID server '%s'" % id_server, + Codes.SERVER_NOT_TRUSTED + ) + + params = { + 'country': country, + 'phone_number': phone_number, + 'client_secret': client_secret, + 'send_attempt': send_attempt, + } + params.update(kwargs) + + try: + data = yield self.http_client.post_json_get_json( + "https://%s%s" % ( + id_server, + "/_matrix/identity/api/v1/validate/msisdn/requestToken" + ), + params + ) + defer.returnValue(data) + except CodeMessageException as e: + logger.info("Proxied requestToken failed: %r", e) + raise e -- cgit 1.4.1 From ad882cd54d8349750f363e6127eca14a2e52b2b6 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 1 Mar 2017 18:08:51 +0000 Subject: Just return the deferred straight off defer.returnValue doth not maketh a generator: it would need a yield to be a generator, and this doesn't need a yield. --- synapse/handlers/auth.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'synapse/handlers') diff --git a/synapse/handlers/auth.py b/synapse/handlers/auth.py index 448bc0b31f..2ea1d17ca5 100644 --- a/synapse/handlers/auth.py +++ b/synapse/handlers/auth.py @@ -309,13 +309,11 @@ class AuthHandler(BaseHandler): defer.returnValue(True) raise LoginError(401, "", errcode=Codes.UNAUTHORIZED) - @defer.inlineCallbacks def _check_email_identity(self, authdict, _): - defer.returnValue(self._check_threepid('email', authdict)) + return self._check_threepid('email', authdict) - @defer.inlineCallbacks def _check_msisdn(self, authdict, _): - defer.returnValue(self._check_threepid('msisdn', authdict)) + return self._check_threepid('msisdn', authdict) @defer.inlineCallbacks def _check_dummy_auth(self, authdict, _): -- cgit 1.4.1 From 402a7bf63d0b8fc715ae6659c3b451e1bd44b0f2 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 8 Mar 2017 09:33:40 +0000 Subject: Fix pep8 --- synapse/handlers/auth.py | 2 +- synapse/rest/client/v1/login.py | 6 +++--- synapse/rest/client/v2_alpha/account.py | 4 ++-- synapse/rest/client/v2_alpha/register.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'synapse/handlers') diff --git a/synapse/handlers/auth.py b/synapse/handlers/auth.py index 2ea1d17ca5..620591b165 100644 --- a/synapse/handlers/auth.py +++ b/synapse/handlers/auth.py @@ -344,7 +344,7 @@ class AuthHandler(BaseHandler): medium, threepid['medium'], ), errcode=Codes.UNAUTHORIZED - ) + ) threepid['threepid_creds'] = authdict['threepid_creds'] diff --git a/synapse/rest/client/v1/login.py b/synapse/rest/client/v1/login.py index 8de1a02254..337ba5c02d 100644 --- a/synapse/rest/client/v1/login.py +++ b/synapse/rest/client/v1/login.py @@ -80,7 +80,7 @@ def login_id_thirdparty_from_phone(identifier): except phonenumbers.NumberParseException: raise SynapseError(400, "Unable to parse phone number") msisdn = phonenumbers.format_number( - phoneNumber, phonenumbers.PhoneNumberFormat.E164 + phoneNumber, phonenumbers.PhoneNumberFormat.E164 )[1:] return { @@ -188,7 +188,7 @@ class LoginRestServlet(ClientV1RestServlet): # convert threepid identifiers to user IDs if identifier["type"] == "m.id.thirdparty": - if not 'medium' in identifier or not 'address' in identifier: + if 'medium' not in identifier or 'address' not in identifier: raise SynapseError(400, "Invalid thirdparty identifier") address = identifier['address'] @@ -198,7 +198,7 @@ class LoginRestServlet(ClientV1RestServlet): # (See add_threepid in synapse/handlers/auth.py) address = address.lower() user_id = yield self.hs.get_datastore().get_user_id_by_threepid( - identifier['medium'], address + identifier['medium'], address ) if not user_id: raise LoginError(403, "", errcode=Codes.FORBIDDEN) diff --git a/synapse/rest/client/v2_alpha/account.py b/synapse/rest/client/v2_alpha/account.py index cf80f5ca28..06bb3617ec 100644 --- a/synapse/rest/client/v2_alpha/account.py +++ b/synapse/rest/client/v2_alpha/account.py @@ -93,7 +93,7 @@ class MsisdnPasswordRequestTokenRestServlet(RestServlet): except phonenumbers.NumberParseException: raise SynapseError(400, "Unable to parse phone number") msisdn = phonenumbers.format_number( - phoneNumber, phonenumbers.PhoneNumberFormat.E164 + phoneNumber, phonenumbers.PhoneNumberFormat.E164 )[1:] existingUid = yield self.hs.get_datastore().get_user_id_by_threepid( @@ -279,7 +279,7 @@ class MsisdnThreepidRequestTokenRestServlet(RestServlet): except phonenumbers.NumberParseException: raise SynapseError(400, "Unable to parse phone number") msisdn = phonenumbers.format_number( - phoneNumber, phonenumbers.PhoneNumberFormat.E164 + phoneNumber, phonenumbers.PhoneNumberFormat.E164 )[1:] existingUid = yield self.hs.get_datastore().get_user_id_by_threepid( diff --git a/synapse/rest/client/v2_alpha/register.py b/synapse/rest/client/v2_alpha/register.py index 768e753083..ad3c70814d 100644 --- a/synapse/rest/client/v2_alpha/register.py +++ b/synapse/rest/client/v2_alpha/register.py @@ -116,7 +116,7 @@ class MsisdnRegisterRequestTokenRestServlet(RestServlet): except phonenumbers.NumberParseException: raise SynapseError(400, "Unable to parse phone number") msisdn = phonenumbers.format_number( - phoneNumber, phonenumbers.PhoneNumberFormat.E164 + phoneNumber, phonenumbers.PhoneNumberFormat.E164 )[1:] existingUid = yield self.hs.get_datastore().get_user_id_by_threepid( -- cgit 1.4.1 From 88df6c0c9a7ce12e7875680131cac421da87ad60 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 8 Mar 2017 11:03:39 +0000 Subject: Factor out msisdn canonicalisation Plus a couple of other minor fixes --- synapse/handlers/auth.py | 2 +- synapse/rest/client/v1/login.py | 18 +++++------------- synapse/rest/client/v2_alpha/account.py | 21 +++------------------ synapse/rest/client/v2_alpha/register.py | 11 ++--------- 4 files changed, 11 insertions(+), 41 deletions(-) (limited to 'synapse/handlers') diff --git a/synapse/handlers/auth.py b/synapse/handlers/auth.py index 620591b165..b273a4bee7 100644 --- a/synapse/handlers/auth.py +++ b/synapse/handlers/auth.py @@ -321,7 +321,7 @@ class AuthHandler(BaseHandler): defer.returnValue(True) @defer.inlineCallbacks - def _check_threepid(self, medium, authdict, ): + def _check_threepid(self, medium, authdict): yield run_on_reactor() if 'threepid_creds' not in authdict: diff --git a/synapse/rest/client/v1/login.py b/synapse/rest/client/v1/login.py index 337ba5c02d..77a0f00c56 100644 --- a/synapse/rest/client/v1/login.py +++ b/synapse/rest/client/v1/login.py @@ -19,13 +19,13 @@ from synapse.api.errors import SynapseError, LoginError, Codes from synapse.types import UserID from synapse.http.server import finish_request from synapse.http.servlet import parse_json_object_from_request +from synapse.util.msisdn import phone_number_to_msisdn from .base import ClientV1RestServlet, client_path_patterns import simplejson as json import urllib import urlparse -import phonenumbers import logging from saml2 import BINDING_HTTP_POST @@ -61,8 +61,6 @@ def login_submission_legacy_convert(submission): del submission["medium"] del submission["address"] - return submission - def login_id_thirdparty_from_phone(identifier): """ @@ -74,14 +72,8 @@ def login_id_thirdparty_from_phone(identifier): """ if "country" not in identifier or "number" not in identifier: raise SynapseError(400, "Invalid phone-type identifier") - phoneNumber = None - try: - phoneNumber = phonenumbers.parse(identifier["number"], identifier["country"]) - except phonenumbers.NumberParseException: - raise SynapseError(400, "Unable to parse phone number") - msisdn = phonenumbers.format_number( - phoneNumber, phonenumbers.PhoneNumberFormat.E164 - )[1:] + + msisdn = phone_number_to_msisdn(identifier["country"], identifier["number"]) return { "type": "m.id.thirdparty", @@ -173,7 +165,7 @@ class LoginRestServlet(ClientV1RestServlet): if "password" not in login_submission: raise SynapseError(400, "Missing parameter: password") - login_submission = login_submission_legacy_convert(login_submission) + login_submission_legacy_convert(login_submission) if "identifier" not in login_submission: raise SynapseError(400, "Missing param: identifier") @@ -182,7 +174,7 @@ class LoginRestServlet(ClientV1RestServlet): if "type" not in identifier: raise SynapseError(400, "Login identifier has no type") - # convert phone type identifiers to geberic threepids + # convert phone type identifiers to generic threepids if identifier["type"] == "m.id.phone": identifier = login_id_thirdparty_from_phone(identifier) diff --git a/synapse/rest/client/v2_alpha/account.py b/synapse/rest/client/v2_alpha/account.py index 06bb3617ec..199af60fc9 100644 --- a/synapse/rest/client/v2_alpha/account.py +++ b/synapse/rest/client/v2_alpha/account.py @@ -20,13 +20,12 @@ from synapse.api.constants import LoginType from synapse.api.errors import LoginError, SynapseError, Codes from synapse.http.servlet import RestServlet, parse_json_object_from_request from synapse.util.async import run_on_reactor +from synapse.util.msisdn import phone_number_to_msisdn from ._base import client_v2_patterns import logging -import phonenumbers - logger = logging.getLogger(__name__) @@ -87,14 +86,7 @@ class MsisdnPasswordRequestTokenRestServlet(RestServlet): if absent: raise SynapseError(400, "Missing params: %r" % absent, Codes.MISSING_PARAM) - phoneNumber = None - try: - phoneNumber = phonenumbers.parse(body['phone_number'], body['country']) - except phonenumbers.NumberParseException: - raise SynapseError(400, "Unable to parse phone number") - msisdn = phonenumbers.format_number( - phoneNumber, phonenumbers.PhoneNumberFormat.E164 - )[1:] + msisdn = phone_number_to_msisdn(body['country'], body['phone_number']) existingUid = yield self.hs.get_datastore().get_user_id_by_threepid( 'msisdn', msisdn @@ -273,14 +265,7 @@ class MsisdnThreepidRequestTokenRestServlet(RestServlet): if absent: raise SynapseError(400, "Missing params: %r" % absent, Codes.MISSING_PARAM) - phoneNumber = None - try: - phoneNumber = phonenumbers.parse(body['phone_number'], body['country']) - except phonenumbers.NumberParseException: - raise SynapseError(400, "Unable to parse phone number") - msisdn = phonenumbers.format_number( - phoneNumber, phonenumbers.PhoneNumberFormat.E164 - )[1:] + msisdn = phone_number_to_msisdn(body['country'], body['phone_number']) existingUid = yield self.hs.get_datastore().get_user_id_by_threepid( 'msisdn', msisdn diff --git a/synapse/rest/client/v2_alpha/register.py b/synapse/rest/client/v2_alpha/register.py index ad3c70814d..95f9944c49 100644 --- a/synapse/rest/client/v2_alpha/register.py +++ b/synapse/rest/client/v2_alpha/register.py @@ -21,12 +21,12 @@ from synapse.api.auth import get_access_token_from_request, has_access_token from synapse.api.constants import LoginType from synapse.api.errors import SynapseError, Codes, UnrecognizedRequestError from synapse.http.servlet import RestServlet, parse_json_object_from_request +from synapse.util.msisdn import phone_number_to_msisdn from ._base import client_v2_patterns import logging import hmac -import phonenumbers from hashlib import sha1 from synapse.util.async import run_on_reactor @@ -110,14 +110,7 @@ class MsisdnRegisterRequestTokenRestServlet(RestServlet): if len(absent) > 0: raise SynapseError(400, "Missing params: %r" % absent, Codes.MISSING_PARAM) - phoneNumber = None - try: - phoneNumber = phonenumbers.parse(body['phone_number'], body['country']) - except phonenumbers.NumberParseException: - raise SynapseError(400, "Unable to parse phone number") - msisdn = phonenumbers.format_number( - phoneNumber, phonenumbers.PhoneNumberFormat.E164 - )[1:] + msisdn = phone_number_to_msisdn(body['country'], body['phone_number']) existingUid = yield self.hs.get_datastore().get_user_id_by_threepid( 'msisdn', msisdn -- cgit 1.4.1 From 0e0aee25c469fe3ba95d7410da670bc3fd73b510 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 8 Mar 2017 11:46:22 +0000 Subject: Fix log line --- synapse/handlers/auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'synapse/handlers') diff --git a/synapse/handlers/auth.py b/synapse/handlers/auth.py index b273a4bee7..e7a1bb7246 100644 --- a/synapse/handlers/auth.py +++ b/synapse/handlers/auth.py @@ -331,7 +331,7 @@ class AuthHandler(BaseHandler): identity_handler = self.hs.get_handlers().identity_handler - logger.info("Getting validated threepid. threepidcreds: %r" % (threepid_creds,)) + logger.info("Getting validated threepid. threepidcreds: %r", (threepid_creds,)) threepid = yield identity_handler.threepid_from_creds(threepid_creds) if not threepid: -- cgit 1.4.1