From d12c7809d375ee6ce275c0d9d6ce8ab3647c3537 Mon Sep 17 00:00:00 2001 From: Michel Jouvin Date: Wed, 13 Dec 2023 18:21:18 +0100 Subject: [PATCH] Add ldap_or_authinfo identity provider (#42) Variant of the ldap provider with a fallback to data from the auth provider. This is particularly useful with shibboleth where the auth provider already has all the data and the identity provider would just pass them through anyway. --- flask_multipass/providers/ldap/__init__.py | 4 ++-- flask_multipass/providers/ldap/providers.py | 20 ++++++++++++++++++++ setup.cfg | 1 + 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/flask_multipass/providers/ldap/__init__.py b/flask_multipass/providers/ldap/__init__.py index ff8e7b4..bd9aabf 100644 --- a/flask_multipass/providers/ldap/__init__.py +++ b/flask_multipass/providers/ldap/__init__.py @@ -4,7 +4,7 @@ # Flask-Multipass is free software; you can redistribute it # and/or modify it under the terms of the Revised BSD License. -from .providers import LDAPAuthProvider, LDAPGroup, LDAPIdentityProvider +from .providers import LDAPAuthProvider, LDAPGroup, LDAPIdentityProvider, AuthFallbackLDAPIdentityProvider -__all__ = ('LDAPAuthProvider', 'LDAPGroup', 'LDAPIdentityProvider') +__all__ = ('LDAPAuthProvider', 'LDAPGroup', 'LDAPIdentityProvider', 'AuthFallbackLDAPIdentityProvider') diff --git a/flask_multipass/providers/ldap/providers.py b/flask_multipass/providers/ldap/providers.py index f8a34a1..4a0d941 100644 --- a/flask_multipass/providers/ldap/providers.py +++ b/flask_multipass/providers/ldap/providers.py @@ -232,3 +232,23 @@ def search_groups(self, name, exact=False): for group_dn, group_data in self._search_groups(search_filter): group_name = to_unicode(group_data[self.ldap_settings['gid']][0]) yield self.group_class(self, group_name, group_dn) + + +class AuthFallbackLDAPIdentityProvider(LDAPIdentityProvider): + """Provides identity information using LDAP with a fallback to auth provider data. + + This identity provider is meant to be used together with an auth provider that provides + all the required data (in particular the Shibboleth provider). + + By default it will use only the identifier from the auth provider and look up all the data + from LDAP. + + In case the user does not have data in LDAP however, the data provided from the auth provider + will be used. + """ + + def get_identity_from_auth(self, auth_info): + identifier = auth_info.data.get('identifier') + if identity := super().get_identity_from_auth(auth_info): + return identity + return IdentityInfo(self, identifier=identifier, **auth_info.data) diff --git a/setup.cfg b/setup.cfg index dc18b87..6b253ff 100644 --- a/setup.cfg +++ b/setup.cfg @@ -59,6 +59,7 @@ flask_multipass.auth_providers = static = flask_multipass.providers.static:StaticAuthProvider flask_multipass.identity_providers = ldap = flask_multipass.providers.ldap:LDAPIdentityProvider + ldap_or_authinfo = flask_multipass.providers.ldap:AuthFallbackLDAPIdentityProvider authlib = flask_multipass.providers.authlib:AuthlibIdentityProvider saml = flask_multipass.providers.saml:SAMLIdentityProvider shibboleth = flask_multipass.providers.shibboleth:ShibbolethIdentityProvider