def get_auth(self, username, password, authoritative_source, auth_options=None):
        """ Returns an authentication object.
    
            Examines the auth backend given after the '@' in the username and
            returns a suitable instance of a subclass of the BaseAuth class.

            * `username` [string]
                Username to authenticate as.
            * `password` [string]
                Password to authenticate with.
            * `authoritative_source` [string]
                Authoritative source of the query.
            * `auth_options` [dict]
                A dict which, if authenticated as a trusted user, can override
                `username` and `authoritative_source`.
        """

        if auth_options is None:
            auth_options = {}

        # validate arguments
        if (authoritative_source is None):
            raise AuthError("Missing authoritative_source.")

        # remove invalid cache entries
        rem = list()
        for key in self._auth_cache:
            if self._auth_cache[key]['valid_until'] < datetime.utcnow():
                rem.append(key)
        for key in rem:
            del(self._auth_cache[key])

        user_authbackend = username.rsplit('@', 1)
    
        # Find out what auth backend to use.
        # If no auth backend was specified in username, use default
        backend = ""
        if len(user_authbackend) == 1:
            backend = self._config.get('auth', 'default_backend')
            self._logger.debug("Using default auth backend %s" % backend)
        else:
            backend = user_authbackend[1]
    
        # do we have a cached instance?
        auth_str = ( str(username) + str(password) + str(authoritative_source)
            + str(auth_options) )
        if auth_str in self._auth_cache:
            self._logger.debug('found cached auth object for user %s' % username)
            return self._auth_cache[auth_str]['auth_object']

        # Create auth object
        try:
            auth = self._backends[backend](backend, user_authbackend[0], password, authoritative_source, auth_options)
        except __HOLE__:
            raise AuthError("Invalid auth backend '%s' specified" %
                str(backend))

        # save auth object to cache
        self._auth_cache[auth_str] = {
            'valid_until': datetime.utcnow() + timedelta(seconds=self._config.getint('auth', 'auth_cache_timeout')),
            'auth_object': auth
        }

        return auth
dataset/ETHPy150Open SpriteLink/NIPAP/nipap/nipap/authlib.py/AuthFactory.get_auth