-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
OIDC/OAuth client and Nextcloud backend #8511
Comments
What were the changes you had to make? This is one of the reasons that the mapping provider is pluggable, but if this is a standard setup we should potentially support it. |
synapse/synapse/handlers/oidc_handler.py Line 1100 in 66ac4b1
synapse/synapse/handlers/oidc_handler.py Line 1105 in 66ac4b1
I've no doubt I'm doing it wrong, but I tried all sorts of combinations for subject_claim in homeserver.yaml first: homeserver.yaml:
|
It seems like their response includes stuff that is normally only sent in the HTTP header and the "real" data is under the I checked around briefly but don't see anything about compatibility issues between Nextcloud and authlib (which is the underlying Python library we use for a lot of the OpenID code), so it might just be specific to how we're using the userinfo. It could be reasonable to let the I think you can set Alternately you can provide a completely separate mapping provider (something like) which knows how to deal with this nesting. See the |
That would be ace, and the "logical" approach for me - I'd tried that approach initially (having read that it was just using it as an array key), but it was just throwing me errors, so I hardcoded to prove to myself I wasn't going mad!
Sadly not, I tried that too
I've not written any python in a decade - can you point me to something to get me started, if I end up having to do this way? |
There's some (light) documentation, and then taking a look at the current implementation is probably useful: If you don't plain to make it flexible a lot of that code could go and you can essentially take your patches from above and just plop them in. |
Thanks for your help, @clokep Given the response from that endpoint isn't going to be changing any time soon, I'll write a mapper. Is it likely a pull request would be merged upstream? I may as well share the result if I'm going to the effort of dusting off my python to build it 😊 |
No problem!
I suspect that in core it might make more sense to add a configuration option which (given a response) lets you pull out the user info from it. I'm envisioning something like: synapse/synapse/handlers/oidc_handler.py Lines 440 to 445 in 9789b1f
Feel free to join #synapse-dev:matrix.org if you have any questions! |
Thanks. Obviously I've no real knowledge of the internals of the project (other than the FAQs, the sledgehammer hack-job I did of reverse-engineering the oidc mapper, & the bits of the API docs I've skimmed today) but I can't see a con in enabling the ability to change the root of the returned JSON to the bit which actually follows standards, other than it stops requiring e.g. Nextcloud from properly implementing the spec (and it doesn't look like they'll change their minds any time soon). The pro is the ability for SSO from a Nextcloud/Owncloud/any other non-compliant backend 😊 Our use case is Element Web in Nextcloud doing SSO to anyone who can log into the instance. |
Looks like https://docs.authlib.org/en/latest/client/oauth2.html#compliance-fix-oauth2 |
Good find! 👍 That's probably a more flexible way of handling this, although it doesn't seem that we actually use
The response function would be similar, but not identical since it would be receiving a Twisted response. Overall it should be pretty similar though. |
Here is a simple Nextcloud OIDC mapping provider that is working on my nextcloud + synapse setup: from synapse.handlers.oidc import OidcMappingProvider
from synapse.types import map_username_to_mxid_localpart
class NextcloudOidcMappingProvider(OidcMappingProvider):
def __init__(self, config):
self._config = config
@staticmethod
def parse_config(config):
return {}
def get_remote_user_id(self, userinfo):
return userinfo["ocs"]["data"]["id"]
async def map_user_attributes(self, userinfo, token):
localpart = map_username_to_mxid_localpart(userinfo["ocs"]["data"]["id"])
display_name = userinfo["ocs"]["data"]["display-name"]
return {"localpart": localpart, "display_name": display_name}
async def get_extra_attributes(self, userinfo, token):
extras = {}
return extras I just dropped it into the password_config:
enabled: false
sso:
client_whitelist:
- https://element.example.com/
- https://app.element.io/
oidc_config:
enabled: true
client_id: "changeme"
client_secret: "changeme"
scopes: ["profile", "email"]
issuer: "https://example.com"
discover: false
authorization_endpoint: "https://example.com/index.php/apps/oauth2/authorize"
userinfo_endpoint: "https://example.com/ocs/v2.php/cloud/user?format=json"
token_endpoint: "https://example.com/index.php/apps/oauth2/api/v1/token"
user_mapping_provider:
module: nextcloud_oicd_mapping_provider.NextcloudOidcMappingProvider
config: {} |
I've implemented @Ramblurr's solution and it almost works perfectly, except after logging in with Nextcloud and granting Synapse permission, I get redirected to a Synapse-generated error page saying the session cookie wasn't found: I haven't found a single other thing about this error online except for the source code that generates it, which isn't too helpful really. Firefox's developer tools show the request that returns the error message is sending of cookies: nc_username, nc_token, nc_session_id, and oc_sessionPassphrase. I even have Nextcloud and Synapse using the same subdomain, with Matrix behind an Apache proxy, so it's not some browser security problem. |
I was able to sucessfully log some next cloud users in using the provider submitted by Ramblurr, however I'm not able to re-login to the same account from another device. I receive the below error:
I'm able to sign in using a password after I created my user on a moblie device and set a password, but this defeats the value of using a central identity provider. |
Add |
Does it matter that I'm using a According to this doc, the de-duplication only applies to the situation where two providers return the same username assuming two different people are registering (i.e. John Doe: jdoe and Jerry Doe: jdoe registers Jerry Doe as jdoe1) https://matrix-org.github.io/synapse/develop/sso_mapping_providers.html So my issue is that even though my users are all registered with idp-nextcloud in the user_external_ids table, but is being detected as a new signup.
I also added this to the Nextcloud OIDC mapping provider, but doesn't improve it either
remove ++, obviously
|
Looks like a bug introduced in #10108. Filed as #12432. https://github.com/matrix-org/synapse/pull/10108/files#diff-05be763854c3b4a72fd8c85ffb5a6b3a10da786f46c53ca4b64d1f150d8fc992R469-R470 Because As a workaround, you can try disabling |
Thanks, turning this off does address the issue. |
#14753 should add support for this. |
Starting in Synapse v1.75.0 you should be able to do something like: oidc_config:
enabled: true
discover: false
issuer: "https://<>/"
client_id: "<>"
client_secret: "<>"
authorization_endpoint: "https://<>/apps/oauth2/authorize"
token_endpoint: "https://<>/apps/oauth2/api/v1/token"
userinfo_endpoint: "https://<>/ocs/v2.php/cloud/user?format=json"
skip_verification: false
scopes: ["nc doesn't implement"]
user_mapping_provider:
config:
subject_claim: "{{ user.ocs.data.id }}"
localpart_template: "{{ user.login }}"
display_name_template: "{{ user.name }}" (Note that I used |
I'm so pleased to see this get merged upstream 🎉 |
Nice, just needed to adjust it slightly for me to work:
|
For me, I use
|
Description:
When using Nextcloud as an external identity provider, its JSON response from the userinfo endpoint is as follows:
Which obviously isn't mapped properly.
I've manually hacked the OIDC mapping provider so it brings in the id, but it'd be great if someone who knew what they were doing on the Synapse side could make this connection work properly!
The text was updated successfully, but these errors were encountered: