From b6bdebbc4a710eb1294c5e757e1873874ea07feb Mon Sep 17 00:00:00 2001 From: David Mehren Date: Tue, 23 Nov 2021 11:17:33 +0100 Subject: [PATCH 1/2] Port to new module API This ports the auth provider to the new module API of Synapse 1.46+. Docs: https://matrix-org.github.io/synapse/latest/modules/password_auth_provider_callbacks.html Based on https://github.com/anishihara/matrix-synapse-rest-password-provider/commit/6c29f4deddab589bf9f6b4d37dd4b207e5a55c7b by @anishihara Fixes https://github.com/ma1uta/matrix-synapse-rest-password-provider/issues/9 --- README.md | 8 ++++++-- rest_auth_provider.py | 39 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ddf1a24..92cb2c1 100644 --- a/README.md +++ b/README.md @@ -30,15 +30,19 @@ sudo pip install git+https://github.com/ma1uta/matrix-synapse-rest-password-prov If the command fail, double check that the python version still matches. If not, please let us know by opening an issue. ## Configure -Add or amend the `password_providers` entry like so: +Add or amend the `modules` entry like so: ```yaml -password_providers: +modules: - module: "rest_auth_provider.RestAuthProvider" config: endpoint: "http://change.me.example.com:12345" ``` Set `endpoint` to the value documented with the endpoint provider. +**NOTE:** This requires Synapse 1.46 or later! If you migrate from the legacy `password_providers`, make sure +to remove the old `RestAuthProvider` entry. If the `password_providers` list is empty, you can also remove it completely or +comment it out. + ## Use 1. Install, configure, restart synapse 2. Try to login with a valid username and password for the endpoint configured diff --git a/rest_auth_provider.py b/rest_auth_provider.py index 35f0695..b700d30 100644 --- a/rest_auth_provider.py +++ b/rest_auth_provider.py @@ -20,17 +20,20 @@ # import logging +from typing import Tuple, Optional, Callable, Awaitable + import requests -import json import time +import synapse +from synapse import module_api logger = logging.getLogger(__name__) class RestAuthProvider(object): - def __init__(self, config, account_handler): - self.account_handler = account_handler + def __init__(self, config: dict, api: module_api): + self.account_handler = api if not config.endpoint: raise RuntimeError('Missing endpoint config') @@ -42,6 +45,36 @@ def __init__(self, config, account_handler): logger.info('Endpoint: %s', self.endpoint) logger.info('Enforce lowercase username during registration: %s', self.regLower) + # register an auth callback handler + # see https://matrix-org.github.io/synapse/latest/modules/password_auth_provider_callbacks.html + api.register_password_auth_provider_callbacks( + auth_checkers={ + ("m.login.password", ("password",)): self.check_m_login_password + } + ) + + async def check_m_login_password(self, username: str, + login_type: str, + login_dict: "synapse.module_api.JsonDict") -> Optional[ + Tuple[ + str, + Optional[Callable[["synapse.module_api.LoginResponse"], Awaitable[None]]], + ] + ]: + if login_type != "m.login.password": + return None + + # get the complete MXID + mxid = self.account_handler.get_qualified_user_id(username) + + # check if the password is valid with the old function + password_valid = await self.check_password(mxid, login_dict.get("password")) + + if password_valid: + return mxid, None + else: + return None + async def check_password(self, user_id, password): logger.info("Got password check for " + user_id) data = {'user': {'id': user_id, 'password': password}} From 1010ef4e8f0110b33d02eeb7d9700689d822b0c2 Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Wed, 24 May 2023 23:49:23 -0400 Subject: [PATCH 2/2] Update set_profile_displayname to use UserID type This is required as the function was updated to take this explicit type, rather than just the localpart, in matrix-org/synapse#15458 as part of version 1.83. This is stacked atop #10 to ensure everything is updated. --- rest_auth_provider.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rest_auth_provider.py b/rest_auth_provider.py index b700d30..d824e2b 100644 --- a/rest_auth_provider.py +++ b/rest_auth_provider.py @@ -26,6 +26,7 @@ import time import synapse from synapse import module_api +from synapse.types import UserID logger = logging.getLogger(__name__) @@ -91,7 +92,9 @@ async def check_password(self, user_id, password): logger.info("User not authenticated") return False + types_user_id = UserID.from_string(user_id) localpart = user_id.split(":", 1)[0][1:] + domain = user_id.split(":", 1)[1][1:] logger.info("User %s authenticated", user_id) registration = False @@ -117,7 +120,7 @@ async def check_password(self, user_id, password): if "display_name" in profile and ((registration and self.config.setNameOnRegister) or (self.config.setNameOnLogin)): display_name = profile["display_name"] logger.info("Setting display name to '%s' based on profile data", display_name) - await store.set_profile_displayname(localpart, display_name) + await store.set_profile_displayname(types_user_id, display_name) else: logger.info("Display name was not set because it was not given or policy restricted it")