Performs authentication using simplepam
        
        This function calls simplepam's authenticate function and returns
        status of authentication using PAM and token object (of type
        self.token_type)

        :param username: username in Linux

        :param password: password for username

        :param **token_context: additional args with keys for token generator

def authenticate(self, username, password, **token_context):
        """Performs authentication using simplepam
        
        This function calls simplepam's authenticate function and returns
        status of authentication using PAM and token object (of type
        self.token_type)

        :param username: username in Linux

        :param password: password for username

        :param **token_context: additional args with keys for token generator
        """
        log.info("Trying to authenticate user: '%s'", username)
        if simplepam.authenticate(username, password):
            expire = datetime.now() + timedelta(seconds=self.token_lifetime)
            log.info("Token will be valid to %s", expire.strftime('%c'))

            refresh_expire = -1
            if self.refresh_token_lifetime != -1:
                refresh_expire = datetime.now() + timedelta(seconds=self.refresh_token_lifetime)
                log.info("Refresh token will be valid to %s", refresh_expire.strftime('%c'))

            token = self.token_type(self.app.secret_key, username, expire, **token_context)
            token.context['salt'] = urandom(120).encode('base-64')

            refresh_context = token_context.copy()
            refresh_context['refresh_salt'] = urandom(120).encode('base-64')
            refresh_token = self.token_type(self.app.secret_key, username, refresh_expire, **refresh_context)

            self.token_storage.set(token)
            self.refresh_token_storage.set(refresh_token)
            return (True, token, refresh_token)
    
        log.warning("Couldn't authenticate user: %s", username)
        return (False, None, None)