def ldap_context(settings, use_cache=True): """Establishes an LDAP session context. Establishes a connection to the LDAP server from the `uri` in the ``settings`` and makes the context available in ``current_ldap``. Yields a namedtuple containing the connection to the server and the provider settings. :param settings: dict -- The settings for a LDAP provider. :param use_cache: bool -- If the connection should be cached. """ try: connection = ldap_connect(settings, use_cache=use_cache) ldap_ctx = LDAPContext(connection=connection, settings=settings) _ldap_ctx_stack.push(ldap_ctx) try: yield ldap_ctx except ldap.LDAPError: # If something went wrong we get rid of cached connections. # This is mostly for the python shell where you have a very # long-living application context that usually results in # the ldap connection timing out. _clear_ldap_cache() raise finally: assert _ldap_ctx_stack.pop( ) is ldap_ctx, "Popped wrong LDAP context" except ldap.SERVER_DOWN: if has_app_context() and current_app.debug: raise raise MultipassException("The LDAP server is unreachable") except ldap.INVALID_CREDENTIALS: if has_app_context() and current_app.debug: raise raise ValueError("Invalid bind credentials") except ldap.SIZELIMIT_EXCEEDED: raise MultipassException( "Size limit exceeded (try setting a smaller page size)") except ldap.TIMELIMIT_EXCEEDED: raise MultipassException( "The time limit for the operation has been exceeded.") except ldap.TIMEOUT: raise MultipassException("The operation timed out.") except ldap.FILTER_ERROR: raise ValueError( "The filter supplied to the operation is invalid. " "(This is most likely due to a bad user or group filter.")
def __init__(self, *args, **kwargs): super(ShibbolethAuthProvider, self).__init__(*args, **kwargs) self.settings.setdefault('attrs_prefix', 'ADFS_') if not self.settings.get('callback_uri'): raise MultipassException("`callback_uri` must be specified in the provider settings") self.shibboleth_endpoint = '_flaskmultipass_shibboleth_' + self.name current_app.add_url_rule(self.settings['callback_uri'], self.shibboleth_endpoint, self._shibboleth_callback, methods=('GET', 'POST'))
def search_identities_ex(self, criteria, exact=False, limit=None): if any(len(x) != 1 for x in criteria.values()): # Unfortunately the API does not support OR filters (yet?). # Fortunately we never search for more than one value anyway, except for emails when # looking up identities based on the user's email address. if len(criteria) != 1: raise MultipassException( 'This provider does not support multiple values for a search criterion', provider=self) field, values = dict(criteria).popitem() seen = set() total = 0 all_identities = [] for value in values: identities = self.search_identities_ex({field: [value]}, exact=exact, limit=limit)[0] for identity in identities: if identity.identifier not in seen: seen.add(identity.identifier) all_identities.append(identity) total += 1 return all_identities, total criteria = {k: next(iter(v)) for k, v in criteria.items()} op = 'eq' if exact else 'contains' api_criteria = [ '{}:{}:{}'.format(k, op, v) for k, v in criteria.items() ] api_criteria.append('type:eq:Person') api_criteria += self.settings['extra_search_filters'] params = { 'limit': limit or 5000, 'filter': api_criteria, 'field': [ 'upn', 'firstName', 'lastName', 'displayName', 'instituteName', 'primaryAccountEmail', ], } with self._get_api_session() as api_session: results, total = self._fetch_all(api_session, '/api/v1.0/Identity', params, limit=limit) identities = [] for res in results: del res['id'] identities.append(IdentityInfo(self, res['upn'], **res)) return identities, total
def __init__(self, *args, **kwargs): super(CASAuthProvider, self).__init__(*args, **kwargs) self.settings.setdefault('callback_uri', '/cas_auth/{}'.format(self.name)) if not self.settings.get('cas_url_base'): raise MultipassException( "`cas_url_base` must be specified in the provider settings") self.cas_client = CASClient(self.settings['cas_url_base'], auth_prefix='') self.cas_endpoint = '_flaskmultipass_cas_' + self.name current_app.add_url_rule(self.settings['callback_uri'], self.cas_endpoint, self._authorize_callback, methods=('GET', 'POST'))
def __init__(self, *args, **kwargs): super(ShibbolethAuthProvider, self).__init__(*args, **kwargs) # convert everything to lowercase (headers/WSGI vars are case-insensitive) self.attrs_prefix = self.settings.setdefault('attrs_prefix', 'ADFS_').lower() self.attrs = [attr.lower() for attr in self.settings.get('attrs')] if not self.settings.get('callback_uri'): raise MultipassException( "`callback_uri` must be specified in the provider settings", provider=self) self.from_headers = self.settings.get('from_headers', False) self.shibboleth_endpoint = '_flaskmultipass_shibboleth_' + self.name current_app.add_url_rule(self.settings['callback_uri'], self.shibboleth_endpoint, self._shibboleth_callback, methods=('GET', 'POST'))