Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Allow SAML username provider plugins #6411

Merged
merged 37 commits into from Dec 10, 2019
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
b31adc6
Allow SAML username provider plugins
anoadragon453 Nov 25, 2019
11805ba
Add changelog
anoadragon453 Nov 25, 2019
82b81c0
Apply suggestions from code review
anoadragon453 Nov 27, 2019
f3a3eb4
typo
anoadragon453 Nov 27, 2019
da849c4
Provide a defeault mapping provider class
anoadragon453 Nov 27, 2019
b1a0a5b
wip saml mapping provider documentation
anoadragon453 Nov 27, 2019
466b28b
Add SAML mapping provider docs
anoadragon453 Nov 28, 2019
0985eb6
Pass the whole saml response object to the provider
anoadragon453 Nov 28, 2019
ce22034
Merge branch 'anoa/saml_username_provider' of github.com:matrix-org/s…
anoadragon453 Nov 28, 2019
595e947
Keep saml2_mxid_source_attribute object for SamlHandler
anoadragon453 Nov 28, 2019
6fec3a4
Fix if statement logic
anoadragon453 Nov 28, 2019
7eecd6c
Load module before doing most of the rest of the saml config
anoadragon453 Nov 28, 2019
fcb31ef
Properly pull in backwards compatible options
anoadragon453 Nov 28, 2019
0a42261
Fix argument to load_module
anoadragon453 Nov 28, 2019
5f03ec0
nostatic
anoadragon453 Nov 28, 2019
81688f4
Remove parse_config method
anoadragon453 Nov 28, 2019
e7cb32e
Fix reference to user mapping provider config
anoadragon453 Nov 28, 2019
e892842
Pull user mapping provider module from the right place
anoadragon453 Nov 28, 2019
169d369
Create an instance of the module's class first
anoadragon453 Nov 28, 2019
c0c75e5
Cleanup and fix var names
anoadragon453 Nov 29, 2019
27b5f0f
Remove comma
anoadragon453 Nov 29, 2019
aac1ab5
Deprecation warning, module config, cleanup and processing reordering
anoadragon453 Dec 4, 2019
1d0f2b2
Small fixes. Remove hs.config.saml2_mxid_source_attribute
anoadragon453 Dec 4, 2019
ba07fc2
Non-functional logging change. Doc update
anoadragon453 Dec 6, 2019
22a6b3c
Provider returns req/opt attrs, pass config to the provider, logging …
anoadragon453 Dec 6, 2019
9b85d7c
Remove modifications to load_module
anoadragon453 Dec 6, 2019
dcc6fe9
Address review comments
anoadragon453 Dec 9, 2019
e15fc6a
Fix typing statement
anoadragon453 Dec 9, 2019
f5dcbf5
lint
anoadragon453 Dec 9, 2019
22ead4f
Ensure parse_config doesn't fail if config: is None
anoadragon453 Dec 9, 2019
b8dd5ab
Fix attribute-retrieving method name
anoadragon453 Dec 9, 2019
e9bedc5
Merge branch 'develop' of github.com:matrix-org/synapse into anoa/sam…
anoadragon453 Dec 9, 2019
87c9e7c
Add logging for what's returned by the provider
anoadragon453 Dec 9, 2019
9f01563
Add debug logging and fix config values being None
anoadragon453 Dec 10, 2019
e918990
Polish
anoadragon453 Dec 10, 2019
5b2281e
Comment cleanup
anoadragon453 Dec 10, 2019
8a2e617
Simplify pulling default from module config
anoadragon453 Dec 10, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/6411.feature
@@ -0,0 +1 @@
Allow custom SAML username mapping functinality through an external provider plugin.
79 changes: 79 additions & 0 deletions docs/saml_mapping_providers.md
@@ -0,0 +1,79 @@
# SAML Mapping Providers

A SAML mapping provider is a Python class (loaded via a Python module) that
works out how to map attributes of a SAML response object to Matrix-specific
user attributes. Details such as user ID localpart, displayname, and even avatar
URLs are all things that can be mapped from talking to a SSO service.

As an example, a SSO service may return the email address
"john.smith@example.com" for a user, whereas Synapse will need to figure out how
to turn that into a displayname when creating a Matrix user for this individual.
It may choose `John Smith`, or `Smith, John [Example.com]` or any number of
variations. As each Synapse configuration may want something different, this is
where SAML mapping providers come into play.

## Enabling Providers

External mapping providers are provided to Synapse in the form of an external
Python module. Retrieve this module from [PyPi](https://pypi.org) or elsewhere,
then tell Synapse where to look for the handler class by editing the
`saml2_config.user_mapping_provider.module` config option.

`saml2_config.user_mapping_provider.config` allows you to provide custom
configuration options to the module. Check with the module's documentation for
what options it provides (if any). The options listed by default are for the
user mapping provider built in to Synapse. If using a custom module, you should
comment these options out and use those specified by the module instead.

## Building a Custom Mapping Provider

A custom mapping provider must specify the following methods:

* `__init__(self, parsed_config)`
- Arguments:
- `config` - A configuration object that is the return value of the
`parse_config` method. You should set any configuration options needed
by the module here.
* `saml_response_to_user_attributes(self, saml_response, failures)`
- Arguments:
- `saml_response` - A `saml2.response.AuthnResponse` object to extract user
information from.
- `failures` - An `int` that represents the amount of times the returned
mxid localpart mapping has failed. This should be used
to create a deduplicated mxid localpart which should be
returned instead. For example, if this method returns
`john.doe` as the value of `mxid_localpart` in the returned
dict, and that is already taken on the homeserver, this
method will be called again with the same parameters but
with failures=1. The method should then return a different
`mxid_localpart` value, such as `john.doe1`.
- This method must return a dictionary, which will then be used by Synapse
to build a new user. The following keys are allowed:
* `mxid_localpart` - Required. The mxid localpart of the new user.
* `displayname` - The displayname of the new user.
* `parse_config(config)`
- This method should have the `@staticmethod` decoration.
- Arguments:
- `config` - A `dict` representing the parsed content of the
`saml2_config.user_mapping_provider.config` homeserver config option.
Runs on homeserver startup. Providers should extract any option values
they need here.
- Whatever is returned will be passed back to the user mapping provider module's
`__init__` method during construction.
* `get_required_attributes(config)`
anoadragon453 marked this conversation as resolved.
Show resolved Hide resolved
- This method should have the `@staticmethod` decoration.
- Arguments:
- `config` - A `dict` representing the parsed content of the
`saml2_config.user_mapping_provider.config` homeserver config option.
Runs on homeserver startup. Providers should extract any option values
they need here.
- Returns a tuple of two sets. The first set equates to the saml auth
response attributes that are required for the module to function, whereas
the second set consists of those attributes which can be used if available,
but are not necessary.

## Synapse's Default Provider

Synapse has a built-in SAML mapping provider if a custom provider isn't
specified in the config. It is located at
[`synapse.handlers.saml_handler.DefaultSamlMappingProvider`](../synapse/handlers/saml_handler.py).
61 changes: 43 additions & 18 deletions docs/sample_config.yaml
Expand Up @@ -1186,33 +1186,58 @@ saml2_config:
#
#config_path: "CONFDIR/sp_conf.py"

# the lifetime of a SAML session. This defines how long a user has to
# The lifetime of a SAML session. This defines how long a user has to
# complete the authentication process, if allow_unsolicited is unset.
# The default is 5 minutes.
#
#saml_session_lifetime: 5m

# The SAML attribute (after mapping via the attribute maps) to use to derive
# the Matrix ID from. 'uid' by default.
# An external module can be provided here as a custom solution to
# mapping the above configured saml attribute onto a matrix ID.
anoadragon453 marked this conversation as resolved.
Show resolved Hide resolved
#
#mxid_source_attribute: displayName

# The mapping system to use for mapping the saml attribute onto a matrix ID.
# Options include:
# * 'hexencode' (which maps unpermitted characters to '=xx')
# * 'dotreplace' (which replaces unpermitted characters with '.').
# The default is 'hexencode'.
#
#mxid_mapping: dotreplace
user_mapping_provider:
# The custom module's class. Uncomment to use a custom module.
#
#module: mapping_provider.SamlMappingProvider

# In previous versions of synapse, the mapping from SAML attribute to MXID was
# always calculated dynamically rather than stored in a table. For backwards-
# compatibility, we will look for user_ids matching such a pattern before
# creating a new account.
# Custom configuration values for the module. Below options are
# intended for the built-in provider, they should be changed if
# using a custom module. This section will be passed as a Python
# dictionary to the module's `parse_config` method.
#
config:
# The SAML attribute (after mapping via the attribute maps) to use
# to derive the Matrix ID from. 'uid' by default.
#
# Note: This used to be configured by the
# saml2_config.mxid_source_attribute option. If that is still
# defined, its value will be used instead.
#
#mxid_source_attribute: displayName

# The mapping system to use for mapping the saml attribute onto a
# matrix ID.
#
# Options include:
# * 'hexencode' (which maps unpermitted characters to '=xx')
# * 'dotreplace' (which replaces unpermitted characters with
# '.').
# The default is 'hexencode'.
#
# Note: This used to be configured by the
# saml2_config.mxid_mapping option. If that is still defined, its
# value will be used instead.
#
#mxid_mapping: dotreplace

# In previous versions of synapse, the mapping from SAML attribute to
# MXID was always calculated dynamically rather than stored in a
# table. For backwards- compatibility, we will look for user_ids
# matching such a pattern before creating a new account.
#
# This setting controls the SAML attribute which will be used for this
# backwards-compatibility lookup. Typically it should be 'uid', but if the
# attribute maps are changed, it may be necessary to change it.
# backwards-compatibility lookup. Typically it should be 'uid', but if
# the attribute maps are changed, it may be necessary to change it.
#
# The default is 'uid'.
#
Expand Down