Authentication¶
Indico uses Flask-Multipass to handle authentication, searching for users in an external database, and externally managed groups. This means any Flask-Multipass authentication/identity provider can be used in Indico without any modifications to Indico itself.
For a description of the basic settings regarding local accounts (managed within Indico itself), see the general indico config documentation. This guide focuses solely on advanced authentication methods and how to configure them in Indico.
Configuration¶
Authentication providers¶
Authentication providers handle the login process, i.e. asking for user credentials or redirecting to an external site in case of SSO.
The AUTH_PROVIDERS
setting is Indico’s equivalent to the
MULTIPASS_AUTH_PROVIDERS
setting of Flask-Multipass.
It must be set to a dict mapping a unique (internal) name of the auth
provider (e.g. mycompany-ldap
) to a dict of whatever data is
needed for the given provider.
The following keys are available in the provider data:
type
– Required. The type of the provider. Valid values are e.g.ldap
,authlib
,shibboleth
, and whatever custom providers you have installed.title
– The title of the provider (shown on the login page). If omitted, the provider name is used.default
– Must be set toTrue
for exactly one form-based provider in case more than one such provider is used. The login form of the default provider is displayed when opening the login page so it should be the provider that most people use.logo_url
– If set, the referenced image will be used as the background image of this provider’s login button (on the login page).Any provider-specific settings.
Identity providers¶
Identity providers get data about a user who logged in (based on the information passed on by the authentication provider) and also handle searching of external users and groups.
The IDENTITY_PROVIDERS
setting is Indico’s equivalent to the
MULTIPASS_IDENTITY_PROVIDERS
setting of Flask-Multipass.
It must be set to a dict mapping a unique (internal) name of the
identity provider (e.g. mycompany-ldap
) to a dict of whatever
data is needed for the given provider. Note that once an identity
provider has been used, its name must not be changed.
The following keys are available in the provider data:
type
– Required. The type of the provider. Valid values are e.g.ldap
,authlib
,shibboleth
, and whatever custom providers you have installed.title
– The title of the provider (shown in the account list of the user profile). If omitted, the provider name is used.trusted_email
– Set this toTrue
if all email addresses received from the provider are trustworthy, i.e. if it is guaranteed that an email address actually belongs to the user (either because it’s coming from a trusted employee database or the provider is known to send verification emails). If an email is trusted, Indico will use it immediately to start the signup process or associate an existing account with a matching email address. Otherwise a verification email is sent to prove that the user has access to the email address, which is less user-friendly but extremely important to prevent malicious takeovers of Indico accounts.group_cache_ttl
– Set this to the number in seconds for which group membership check results should be cached, or 0 to disable the cache. You may also set it to a list where the first element is the cache duration for positive checks and the second element the duration for negative checks. Note that you usually do NOT need to set this at all, the default of 1800 seconds is reasonable in most cases, and unless you use a custom multipass backend that has its own cache or is very fast when checking membership on the fly it is best to not touch this at all.moderated
– Set this toTrue
if you want to require manual approval of the registration by an Indico admin. This results in the same workflow asLOCAL_MODERATION
in case of local accounts.synced_fields
– This may be set in no more than one identity provider and enables user data synchronization. Its value should be a set of user attributes that can be synchronized during login. The following attributes can be synchronized:email
,first_name
,last_name
,affiliation
,phone
,address
Due to the unique nature of email addresses, synchronizing them may fail; in that case a warning is displayed and the old email address remains - an Indico admin could merge the users if they are indeed the same person, but this needs to be done manually since merging users is a potentially destructive operation that cannot be undone. It is also strongly recommended to ONLY sync emails if the provider has validated emails (ietrusted_email
set toTrue
); otherwise users would get unvalidated (possibly even invalid) emails set on their account during sync.locked_fields
– A set of fields which are always synchronized with the identity provider. Its value must be a subset of the user attributes listed insynced_fields
, and it it not possible to lock theemail
field. The fields listed here can still be desynchronized by an administrator.locked_field_message
– A message displayed next to the fields listed inlocked_fields
. The purpose is to guide the user on how they should proceed in order to change the locked field’s data.mapping
– A dictionary that maps between keys given by the identity provider and keys expected by Indico for user information. The key of each entry is the Indico-side attribute name; the value is the key under which the data is exposed by the provider. Indico can take user information from the following keys:first_name
,last_name
,email
,affiliation
,phone
,address
. For example, this mapping would use thegivenName
provided by the identity provider to populate the user’sfirst_name
in Indico:'mapping': {'first_name': 'givenName'}
identity_info_keys
– By default, all six attributes listed above will be used if the provider has them (either directly or in some other field specified in themapping
). If you want to restrict the data from a provider (e.g. because the value it provides is known to be useless/incorrect), you can set this to a set containing only the attributes you want to use. Note that external user search requires email addresses, so if you exclude email addresses here, users from this provider will never appear in search results.Any provider-specific settings.
Links between providers¶
By default, authentication and identity providers with the same name
are linked together. If this is not what you want, you can use the
PROVIDER_MAP
setting to manually link providers. This is useful
for advanced cases where you have e.g. both a login form to enter LDAP
credentials and a SSO provider, but want to have a single LDAP identity
provider that can use the username from either SSO or the LDAP login.
In this case you would link both authentication providers to the same
identity provider.
Specific providers¶
LDAP¶
The ldap
authentication/identity providers are available by default,
but to use them you need to install the python-ldap
library using
pip install python-ldap
.
Note
python-ldap
has some extra system dependencies (openldap and
libsasl). How to install them (apt, yum, etc.) depends on your linux
distribution. The package names are usually libsasl2-dev
or
libsasl-dev
and openldap-dev
(or -devel
on some distros).
If one of these libraries is missing, pip
will fail when
installing python-ldap
. Simply re-run the command after
installing the missing library.
Once everything is installed, you can add the LDAP-related settings to
your indico.conf
. Below is an example based on the LDAP config we
use at CERN with Active Directory; you can copy this as a starting point
for your own config and then adapt it to your own environment:
_ldap_config = {
'uri': 'ldaps://...',
'bind_dn': 'cn=***,OU=Users,OU=Organic Units,DC=cern,DC=ch',
'bind_password': '***',
'timeout': 30,
'verify_cert': True,
'page_size': 1500,
'uid': 'cn',
'user_base': 'DC=cern,DC=ch',
'user_filter': '(objectCategory=user)',
'gid': 'cn',
'group_base': 'OU=Workgroups, DC=cern, DC=ch',
'group_filter': '(objectCategory=group)',
'member_of_attr': 'memberOf',
'ad_group_style': True
}
AUTH_PROVIDERS = {
'ldap': {
'type': 'ldap',
'title': 'LDAP',
'ldap': _ldap_config,
'default': True
}
}
IDENTITY_PROVIDERS = {
'ldap': {
'type': 'ldap',
'title': 'LDAP',
'ldap': _ldap_config,
'mapping': {
'first_name': 'givenName',
'last_name': 'sn',
'email': 'mail',
'affiliation': 'company',
'phone': 'telephoneNumber'
},
'trusted_email': True,
'synced_fields': {'first_name', 'last_name', 'affiliation', 'phone', 'address'}
}
}
The LDAP-specific config uses the following keys:
uri
– Required. The URI referring to the LDAP server including the protocol and the port. Useldaps://
for LDAP over SSL/TLS andldap://
with thestarttls
option for a plain LDAP connection with TLS negotiation. The port can be omitted if the LDAP server listens on the default port (636 for LDAP over SSL and 389 for a plain LDAP connection with TLS negotiation).bind_dn
– Required. The distinguished name to bind to the LDAP directory.bind_password
– Required. The password to use together with thebind_dn
to login to the LDAP server.timeout
– The delay in seconds to wait for a reply from the LDAP server (set to-1
to disable). Default:30
verify_cert
– Whether to verify the TLS certificate of the LDAP server. Default:True
starttls
– Whether to use STARTTLS to switch to an encrypted connection. Ignored with anldaps://
URI. Default:False
page_size
– The limit of entries to retrieve at once for a search.0
means no size limit. It is recommended to have at most the size limit imposed by the server. Default:1000
uid
– The attribute whose value is used as an identifier for the user (typically the username). This attribute must be a single-valued attribute whose value is unique for each user. If the attribute is multi-valued, only the first one retrieved will be returned. Default:'uid'
user_base
– Required. The base node for all the nodes which might contain a user.user_filter
– A valid LDAP filter which will select exclusively all users in the subtree from theuser_base
. The combination of theuser_base
and theuser_filter
must match exclusively all the users. Default:'(objectClass=person)'
gid
– The attribute whose value is used as an identifier for the group (typically the group’s name). This attribute must be a single-valued attribute whose value is unique for each group. If the attribute is multi-valued, only the first one retrieved will be returned. Default:'cn'
group_base
– Required. The base node for all the nodes which might contain a group.group_filter
– A valid LDAP filter which will select exclusively all groups in the subtree from thegroup_base
. The combination of thegroup_base
and thegroup_filter
must match exclusively all the groups. Default:'(objectClass=groupOfNames)'
member_of_attr
– The multi-valued attribute of a user containing the list of groups the user is a member of. Default:'memberOf'
Note
In case of SLAPD/OpenLDAP, the member of attribute must be enabled. While it is not enabled by default, the majority of servers will have it enabled. A simple
ldapsearch
for a user member of any group should show if that is the case. If not, you can check this article on information how to enable it on your LDAP server. Note that unless you manage the LDAP server, you need to ask the administrator of that server to do that.ad_group_style
– Whether the server uses Active-Directory-style groups or not. This is only used when checking if a user is a member of a group. If enabled, the code will take advantage of thetokenGroups
attribute of a user to check for nested group membership. Otherwise, it will only look through the values of themember_of_attr
, which should also work for Active Directory, but only for direct membership. Default:False
SAML¶
The saml
authentication/identity providers are available by default,
but to use them you need to install the python3-saml
library using
pip install python3-saml
.
Note
python3-saml
has some extra system dependencies (xmlsec
).
How to install them (apt, yum, etc.) depends on your linux
distribution. The package name is usually libxmlsec1-dev
(or xmlsec1-devel
on RPM-based distros). If this library is
missing, pip
will fail when installing python3-saml
.
Simply re-run the command after installing the missing library.
Once everything is installed, you can add the SAML-related settings to
your indico.conf
. Below is an example you can copy to have a good
starting point for your own config and then adapt it to your own
environment:
_saml_config = {
'sp': {
'entityId': 'indico-saml',
# Depending on your security config below you may need to generate
# a certificate and private key.
# You can use https://www.samltool.com/self_signed_certs.php or
# use openssl for it (which is more secure as it ensures the
# key never leaves your machine)
'x509cert': '',
'privateKey': '',
},
'idp': {
# This metadata is provided by your SAML IdP. You can omit (or
# leave empty) the whole 'idp' section in case you need SP
# metadata to register your app and get the IdP metadata from
# https://indico.example.com/multipass/saml/{auth-provider-name}/metadata
# and then fill in the IdP metadata afterwards.
'entityId': 'https://my-idp.example.com',
'singleSignOnService': {
'url': 'https://my-idp.example.com/saml',
'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
},
'singleLogoutService': {
'url': 'https://my-idp.example.com/saml',
'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
},
'x509cert': ''
},
# These advanced settings allow you to tune the SAML security options.
# Please see the documentation on https://github.com/onelogin/python3-saml
# for details on how they behave. Note that by requiring signatures,
# you usually need to set a cert and key on your SP config.
'security': {
'nameIdEncrypted': False,
'authnRequestsSigned': True,
'logoutRequestSigned': True,
'logoutResponseSigned': True,
'signMetadata': True,
'wantMessagesSigned': True,
'wantAssertionsSigned': True,
'wantNameId' : True,
'wantNameIdEncrypted': False,
'wantAssertionsEncrypted': False,
'allowSingleLabelDomains': False,
'signatureAlgorithm': 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
'digestAlgorithm': 'http://www.w3.org/2001/04/xmlenc#sha256'
}
}
AUTH_PROVIDERS = {
'saml': {
'type': 'saml',
'title': 'SAML SSO',
'saml_config': _saml_config,
# If your IdP is using ADFS you may need to uncomment this. For details, see
# https://github.com/onelogin/python-saml/pull/144
# 'lowercase_urlencoding': True
}
}
IDENTITY_PROVIDERS = {
'saml': {
'type': 'saml',
'title': 'SSO',
'mapping': {
'first_name': 'Firstname',
'last_name': 'Lastname',
'email': 'EmailAddress',
'affiliation': 'HomeInstitute',
},
'trusted_email': True,
# You can use a different field as the unique identifier.
# By default the qualified NameID from SAML is used, but in
# case you want to use something else, any SAML attribute can
# be used.
# 'identifier_field': 'Username'
}
}
If you also have an LDAP server, it may be a good idea to use the
saml
authentication provider and connect it to an ldap
identity provider. This way the user information is retrieved from LDAP
based on a unique identifier of the user that comes from SAML, and you
can still use the search and group functionality provided by LDAP.
To use this, use the AUTH_PROVIDERS
config from above together with
the IDENTITY_PROVIDERS
config from the LDAP section on this page,
and set up a PROVIDER_MAP
that passes the identifier from SAML to
LDAP. The example below assumes that the LDAP username is passed in a
SAML attribute named UPN
.
PROVIDER_MAP = {
'saml': {'identity_provider': 'ldap', 'mapping': {'identifier': 'UPN'}},
}
Shibboleth¶
Changed in version 3.0: SAML is now supported without the need for Apache.
Note
Note that since Indico 3.0 there is a new saml
auth/identity provider
available which does not require Apache/shibd and is thus the recommended
option to use regardless of the web server in use.
The shibboleth
authentication/identity providers are available by
default, but due to how the protocol works you need to use the Apache
webserver to use SAML atuhentication provider.
You can find guides on how to set it up for Alma/Rocky Linux and Debian/Ubuntu.
If you also have an LDAP server, it may be a good idea to use the
shibboleth
authentication provider and connect it to an ldap
identity provider. This way the user information is retrieved from LDAP
based on a unique identifier of the user that comes from SAML, and you
can still use the search and group functionality provided by LDAP.