def validate_user(username, password, htpassfile=None, session={}, request=None): ''' Validate the User with htpassfile or Trac ''' from brain import bconfig result = {} # validate the user with htpassfile or trac username is_valid = False user = None # try from request if not htpassfile and request: htpassfile = request.environ.get('HTPASSFILE', None) # try from brain config if not htpassfile and hasattr(bconfig, '_htpass_path'): htpassfile = bconfig._htpass_path # validate user if username == 'sdss': if htpassfile: htpass = HtpasswdFile(htpassfile) is_valid = htpass.check_password(username, password) user = username else: result['error'] = 'No valid htpasswd file found!' else: result = inspection_authenticate(session, username=username, password=password) is_valid = result['is_valid'] user = result.get('membername', None) return is_valid, user, result
def __init__(self, file_path): """ :param file_path: Path to the file with authentication information. :type file_path: ``str`` """ self._file_path = file_path self._htpasswd_file = HtpasswdFile(path=self._file_path)
def compute_basic_auth(username, password): """Generate hashed HTTP basic auth from traefik_api username+password""" ht = HtpasswdFile() # generate htpassword ht.set_password(username, password) hashed_password = str(ht.to_string()).split(":")[1][:-3] return username + ":" + hashed_password
def verify_pw(username, password): """ return password or None if there isn't one""" credentials = HtpasswdFile(app.config["CREDENTIAL_FILE"]) if not credentials.check_password(username, password): logging.warning("%s tried to login with wrong password", username) return False return True
class HtpasswdAuthenticator(object): """ Handles the user authentication for htpasswd files htpasswd is the location of the htpasswd to use """ def __init__(self): #try to locate the server config and load it server_folder = os.path.join(os.path.expanduser("~"), '.conan_server') server_conf = os.path.join(server_folder, "server.conf") htpasswd_location = os.path.join(server_folder, "plugins", "authentication", ".htpasswd") if os.path.exists(server_conf): conf = ConfigParser() conf.read(server_conf) new_loc = conf.get("server", "htpasswd_file") if os.path.exists(new_loc): htpasswd_location = new_loc self.htpasswd = HtpasswdFile(htpasswd_location) def valid_user(self, username, plain_password): """ username: Username to be authenticated plain_password: The password to authenticate with return: True if match False if don't """ # Update self.htpasswd.load_if_changed() # Verify return username in self.htpasswd.users() and \ self.htpasswd.check_password(username, plain_password)
def _generate_htpassword(self): from passlib.apache import HtpasswdFile ht = HtpasswdFile() ht.set_password(self.traefik_api_username, self.traefik_api_password) self.traefik_api_hashed_password = str( ht.to_string()).split(":")[1][:-3]
def authenticate(passwordFile: HtpasswdFile, credentials: Credentials) -> None: """Checks a name and password combination against a password file. Returns if authentication succeeds. Raises `UnauthorizedLogin` if the given user name and password combination is not accepted. The hashed version of the password will be updated with a new hash function if the current one is depricated. """ name = credentials.name password = credentials.password try: checkPassword(password) except ValueError as ex: raise UnauthorizedLogin(ex) from ex # Have passlib check the password. When passed a None hash, it will # perform a dummy computation to keep the timing consistent. passwordFile.load_if_changed() correct, newHash = passwordFile.context.verify_and_update( password.encode(), passwordFile.get_hash(name)) if not correct: raise UnauthorizedLogin('Authentication failed') if newHash is not None: # Replace hash with better algorithm or config. passwordFile.set_hash(name, newHash) writePasswordFile(passwordFile)
def initPasswordFile(path: Path) -> HtpasswdFile: passwordFile = HtpasswdFile(str(path), default_scheme='portable', new=True) # Marking schemes as deprecated tells passlib to re-hash when a password # is successfully verified. Instead of marking only known insecure schemes # as deprecated, we mark everything except the default scheme. # A good password cannot be brute forced in a reasonable amount of time, # but few people actually use good passwords, so slowing down an attacker # by using the best hash algorithm we have available is useful. orgContext = passwordFile.context defaultScheme = orgContext.default_scheme() deprecated = [ scheme for scheme in orgContext.schemes() if scheme != defaultScheme ] passwordFile.context = orgContext.copy(deprecated=deprecated) try: passwordFile.load() except FileNotFoundError: path.parent.mkdir(parents=True, exist_ok=True) # Create empty file. with path.open('a'): pass return passwordFile
def create_basic_auth_secret( secret_name: str, namespace: str, basic_auth_cred: BasicAuthCred = None, ): """ Creates a secret with the configured TLS certificates in the K8s cluster. Optionally adds credentials for Basic Authentication""" not_empty(secret_name) not_empty(namespace) ctx = kube_ctx namespace_helper = ctx.namespace_helper() namespace_helper.create_if_absent(namespace) secret_helper = ctx.secret_helper() if not secret_helper.get_secret(secret_name, namespace): ht = HtpasswdFile() ht.set_password(basic_auth_cred.user, basic_auth_cred.password) data = { 'auth': ht.to_string().decode('utf-8'), } secret_helper.put_secret( name=secret_name, data=data, namespace=namespace, )
def create_tls_secret(tls_config: TlsConfig, tls_secret_name: str, namespace: str, basic_auth_cred: BasicAuthCred = None): """ Creates a secret with the configured TLS certificates in the K8s cluster. Optionally adds credentials for Basic Authentication""" not_none(tls_config) not_empty(tls_secret_name) not_empty(namespace) ctx = kube_ctx namespace_helper = ctx.namespace_helper() namespace_helper.create_if_absent(namespace) secret_helper = ctx.secret_helper() if not secret_helper.get_secret(tls_secret_name, namespace): data = { 'tls.key': tls_config.private_key(), 'tls.crt': tls_config.certificate(), } if basic_auth_cred: ht = HtpasswdFile() ht.set_password(basic_auth_cred.user, basic_auth_cred.password) data['auth'] = ht.to_string().decode('utf-8') secret_helper.put_secret( name=tls_secret_name, data=data, namespace=namespace, )
def __init__(self, htpasswd_file=".htpasswd", perms_file=".repoperms", keys_file=".rsakeys"): self.htpasswd = HtpasswdFile(htpasswd_file) self.perms_file = perms_file self.keys_file = keys_file
def __init__(self): config = self.get_component_config() if 'file' not in config: raise InsufficientConfiguration(missing='file', component=self.get_component_name()) self.htpasswd = HtpasswdFile(config['file'])
def authenticate(self, request): """Authenticate the provided request.""" if (self.config.password_file is None or self.config.password_file == '.'): return True pwd_file = HtpasswdFile(self.config.password_file) pwd_file.load_if_changed() return pwd_file.check_password(*request.auth)
def groupfinder(username, password, request): ht = HtpasswdFile() ht.load_string(os.environ.get("HTPASSWORDS", "")) if ht.check_password(username, password): return ["admin"] else: return None
def is_user_authenticated(self, username, password): passfile = HtpasswdFile(config['passfile']) # is the user in the password file? if not username in passfile.users(): return False return passfile.check_password(username, password)
def test_make_htpasswd(self): self.server.add_user('testuser', 'testpass') self.server.add_user('xtestuser', 'xtestpass') with NamedTemporaryFile() as file: self.server.make_htpasswd(file.name) ht = HtpasswdFile(file.name) self.assertEqual(['testuser', 'xtestuser'], sorted(ht.users())) self.assertTrue(ht.check_password('testuser', 'testpass'))
class UserDB(): def __init__(self, filename): self.htpasswd = HtpasswdFile(filename) def get_users(self): self.htpasswd.get_users() def check_password(self, user, password): return self.htpasswd.check_password(user, password)
def verify_passwd_hash(username, password): htContent = HtpasswdFile(app.config['HTPASSWD_FILE'], default_scheme='sha256_crypt') passwdHash = htContent.get_hash(username) try: hashMatch = sha256_crypt.verify(password, passwdHash) if hashMatch: return True except ValueError: return False except TypeError: return False
def check_credentials(self, username, password): """ Need to make this file based. """ if os.path.isfile(self.htpasswd): ht = HtpasswdFile(self.htpasswd) if ht.check_password(username, password): return (True) else: return (u"Incorrect username or password.") return (u"Htpasswd file was not found ")
def verify_password(login, password): try: htpasswd_file = HtpasswdFile(current_app.config['HTPASSWD_PATH']) except EnvironmentError: return False if htpasswd_file.check_password(login, password): return True else: g.reason = 'invalid password' return False
def authenticate(self, username, password): htpasswd_file = HtpasswdFile(path=self._file_path) result = htpasswd_file.check_password(username, password) if result is None: LOG.debug('User "%s" doesn\'t exist' % (username)) elif result is False: LOG.debug('Invalid password for user "%s"' % (username)) elif result is True: LOG.debug('Authentication for user "%s" successful' % (username)) return bool(result)
def check_auth(username, password): """This function is called to check if a username / password combination is valid. """ if htpasswd is None: logging.warning("htpasswd not initialized, denying") return False if htpasswd is False: logging.info("htpasswd skipped, because it is set to False") return True ht = HtpasswdFile(htpasswd) return ht.check_password(username, password)
def authenticate_credentials(self, key): ht = HtpasswdFile(settings.PATH_TO_HTPASSWD_FILE) usernames = ht.users() for username in usernames: check_result = ht.check_password(username, key) if check_result: if username == usernames[0]: return (self.get_user('admin'), key) else: return (self.get_user(username), key) raise exceptions.AuthenticationFailed('Invalid token.')
def load_users(self, app): """ Load users from configured file. Args: app (flask.Flask): Flask application to load users from. Raises: IOError: If the configured htpasswd file does not exist. Returns: None """ self.users = HtpasswdFile(app.config['FLASK_HTPASSWD_PATH'])
def add_user(username, password): cwd = os.path.abspath(__file__)[:-8] if os.path.exists(cwd + "login/.htpasswd") == False: ht = HtpasswdFile(cwd + "login/.htpasswd", new=True) result = ht.set_password(username, password) ht.save() return result else: ht = HtpasswdFile(cwd + "login/.htpasswd") result = ht.set_password(username, password) ht.save() if result == False: return True
def validate_user(username, password, htpassfile=None, request=None): ''' Validate the User with htpassfile or Trac Tries to validate a user first with a user login from the htpassfile, and second from a Trac wiki account. Parameters: username (str): The login user id password (str): The login user password htpassfile (str): Optional. The full path to an htpassfile. request (Request): The Flask request object Returns: A tuple of (boolean if the user is valid, the username, and the results dictionary) ''' from brain import bconfig result = {} # validate the user with htpassfile or trac username is_valid = False user = None # try from request if not htpassfile and request: htpassfile = request.environ.get('HTPASSFILE', None) # try from brain config if not htpassfile and hasattr(bconfig, '_htpass_path'): htpassfile = bconfig._htpass_path # validate user if username == 'sdss': if htpassfile: htpass = HtpasswdFile(htpassfile) is_valid = htpass.check_password(username, password) user = username else: result['error'] = 'No valid htpasswd file found!' else: result = collaboration_authenticate(username=username, password=password) is_valid = result['is_valid'] user = result.get('user', None) return is_valid, user, result
def _htpasswd(username, password, **kwargs): ''' Provide authentication via Apache-style htpasswd files ''' from passlib.apache import HtpasswdFile pwfile = HtpasswdFile(kwargs['filename']) # passlib below version 1.6 uses 'verify' function instead of 'check_password' if salt.utils.version_cmp(kwargs['passlib_version'], '1.6') < 0: return pwfile.verify(username, password) else: return pwfile.check_password(username, password)
def authenticate_credentials(self, userid, password, request=None): ht = HtpasswdFile(settings.PATH_TO_HTPASSWD_FILE) result = ht.check_password(userid, password) usernames = ht.users() if result is None: raise exceptions.AuthenticationFailed('Invalid username.') elif not result: raise exceptions.AuthenticationFailed('Invalid password.') else: if userid == usernames[0]: return (self.get_user('admin'), None) else: return (self.get_user(userid), None)
class Auth(dnscherry.auth.Auth): def __init__(self, config, logger=None): self.logout_button = True self.htpasswdfile = self._get_param('auth.htpasswd.file', config, None) self.ht = HtpasswdFile(self.htpasswdfile) def check_credentials(self, username, password): try: return self.ht.check_password(username, password) # older versions of passlib doesn't have check_password except AttributeError: username = str(username) password = str(password) return self.ht.verify(username, password)
def __init__(self): #try to locate the server config and load it server_folder = os.path.join(os.path.expanduser("~"), '.conan_server') server_conf = os.path.join(server_folder, "server.conf") htpasswd_location = os.path.join(server_folder, "plugins", "authentication", ".htpasswd") if os.path.exists(server_conf): conf = ConfigParser() conf.read(server_conf) new_loc = conf.get("server", "htpasswd_file") if os.path.exists(new_loc): htpasswd_location = new_loc self.htpasswd = HtpasswdFile(htpasswd_location)
def __init__(self, conf): auth = conf.get('auth') if auth not in AuthChecker.methods: raise ValueError('unknown auth type: ' + auth) self.auth = auth self.https_only = conf.get('auth_https_only') if auth == 'basic': htpasswd = os.path.join(conf['data_dir'], 'htpasswd.db') htpasswd = conf.get('auth_htpasswd') or htpasswd self.htpasswd = HtpasswdFile(htpasswd) self._log('Using htpasswd: ' + str(htpasswd)) self.realm = conf.get('auth_realm', 'fileshelf')
class TestAuthnz(object): def __init__(self, htpasswd_file=".htpasswd", perms_file=".repoperms", keys_file=".rsakeys"): self.htpasswd = HtpasswdFile(htpasswd_file) self.perms_file = perms_file self.keys_file = keys_file def can_read(self, username, path_info): return self._check_access(username, path_info, "r") def can_write(self, username, path_info): return self._check_access(username, path_info, "w") def _check_access(self, username, path_info, level): if username is None: username = "******" if path_info['repository_fs_path'] is None: return False repo = os.path.basename(path_info['repository_fs_path']) config = SafeConfigParser() config.read(self.perms_file) if not config.has_option(repo, username): return False return level in config.get(repo, username) def check_password(self, username, password): self.htpasswd.load_if_changed() return self.htpasswd.check_password(username, password) def check_publickey(self, username, keyblob): with open(self.keys_file, 'rb') as f: for line in f: try: user, key = line.split(':', 1) if (username == user.strip() and keyblob == keys.Key.fromString(data=key.strip() ).blob()): return True except: log.err(None, "Loading key failed") return False
class FlatFileAuthenticationBackend(BaseAuthenticationBackend): """ Backend which reads authentication information from a local file. Entries need to be in a htpasswd file like format. This means entries can be managed with the htpasswd utility (https://httpd.apache.org/docs/current/programs/htpasswd.html) which ships with Apache HTTP server. Note: This backends depends on the "passlib" library. """ def __init__(self, file_path): """ :param file_path: Path to the file with authentication information. :type file_path: ``str`` """ self._file_path = file_path self._htpasswd_file = HtpasswdFile(path=self._file_path) def authenticate(self, username, password): result = self._htpasswd_file.check_password(username, password) if result is None: LOG.debug('User "%s" doesn\'t exist' % (username)) elif result is False: LOG.debug('Invalid password for user "%s"' % (username)) elif result is True: LOG.debug('Authentication for user "%s" successful' % (username)) return bool(result) def get_user(self, username): pass
def check_user(self, username, password): """ Verify if the username and password are valid and the user can be authenticated against the htpasswd file properly. :param username: the username that matches the user in the htpasswd file. :param password: the password that will be hashed and verified against the htpasswd file. :return: The user itself. """ ht = HtpasswdFile(HTPASSWD_FILE) if username in ht.users(): if ht.check_password(username, password): return self return False
class __FileAuthenticator: '''Takes a htpasswd file path from the HTPASSWD_FILE environment variable. ''' def __init__(self, filename): self.filename = filename self.data = HtpasswdFile(self.filename) def authenticate(self, username, password): """ Returns True if username exists and password is valid, False otherwise """ if self.data.check_password(username, password): # Note: check_password returns None if username does not exists return True return False def get_hash(self, username): """ Returns a hash if username exists, None otherwise """ return self.data.get_hash(username) def find_user(self, username): """ Returns True if usename exists in db, False otherwise """ return username in self.data.users()
def check_password(environ, user, password): from passlib.apache import HtpasswdFile import ConfigParser pathdir = os.path.dirname(os.path.realpath(__file__)) gitaclfile = "%s/gitldapacl.ini" % pathdir #print gitaclfile config = ConfigParser.ConfigParser() config.read(gitaclfile) users_str = config.get("local_users","users") htpwdfile = config.get("local_users","passwd_file") users_lst = users_str.split(',') ht = HtpasswdFile(htpwdfile) users = [] for u in users_lst: u = u.strip() users.append(u) if user in users: if ht.verify(user,password): allowed = False __init_acl() #print "Verified user account %s." % user allowed = uri_can_access_by_user(environ['REQUEST_URI'],user) #if allowed: # print "Can access by user." return allowed else: return False __init_ldap() __init_acl() if __authen_ldap_authenticator.login(user,password): return uri_can_access_by_user(environ['REQUEST_URI'],user) return False
def load_users(self, app): """ Load users from configured file. Args: app (flask.Flask): Flask application to load users from. Raises: IOError: If the configured htpasswd file does not exist. Returns: None """ self.users = HtpasswdFile( app.config['FLASK_HTPASSWD_PATH'] )
class HtpasswdUsers(Component): implements(IUserAuthenticator) implements(IUserTranslator) def __init__(self): config = self.get_component_config() if 'file' not in config: raise InsufficientConfiguration(missing='file', component=self.get_component_name()) self.htpasswd = HtpasswdFile(config['file']) def username_to_user(self, username): self.htpasswd.load_if_changed() if username in self.htpasswd.users(): return User(self.compmgr, username, username=username, full_name=username) def userid_to_user(self, userid): if userid is None or userid == '*': warnings.warn("You should not call this directly. Use cydra.get_user()", DeprecationWarning, stacklevel=2) return User(self.compmgr, '*', username='******', full_name='Guest') self.htpasswd.load_if_changed() if userid in self.htpasswd.users(): return User(self.compmgr, userid, username=userid, full_name=userid) else: # since the client was looking for a specific ID, # we return a dummy user object with empty data return User(self.compmgr, userid, full_name='N/A') def groupid_to_group(self, groupid): pass def user_password(self, user, password): self.htpasswd.load_if_changed() return self.htpasswd.check_password(user.userid, password)
def absent(dest, username, check_mode): """ Ensures user is absent Returns (msg, changed) """ if StrictVersion(passlib.__version__) >= StrictVersion('1.6'): ht = HtpasswdFile(dest, new=False) else: ht = HtpasswdFile(dest) if username not in ht.users(): return ("%s not present" % username, False) else: if not check_mode: ht.delete(username) ht.save() return ("Remove %s" % username, True)
def validate(self): """Validate the needed fields.""" rv = Form.validate(self) if not rv: return False ht = HtpasswdFile(HTPASSWD_FILE) if self.name.data in ht.users(): if ht.check_password(self.name.data, self.passwd.data): ht.set_password(self.name.data, self.newpwd.data) ht.save() return True else: self.passwd.errors.append('Senha Incorreta') return False else: self.name.errors.append('Usuário Desconhecido') return False
class ApachePasswordDB(object): """ Very simple glue between passlib.apache.HtpasswdFile to make it an ICredentialsChecker in Twisted. """ implements(ICredentialsChecker) # we can only implement non-hashing functions as the passwords # may be hashed. credentialInterfaces = ( credentials.IUsernamePassword, ) def __init__(self, filename): self._ht = HtpasswdFile(filename) def requestAvatarId(self, c): if self._ht.check_password(c.username, c.password): # success, return username return defer.succeed(c.username) else: # bad credentials return defer.fail(error.UnauthorizedLogin())
def __init__(self, filename): self.filename = filename self.data = HtpasswdFile(self.filename)
def __init__(self, config, logger=None): self.logout_button = True self.htpasswdfile = self._get_param('auth.htpasswd.file', config, None) self.ht = HtpasswdFile(self.htpasswdfile)
def load_users(filepath): pwd_file = HtpasswdFile(filepath) for user in pwd_file.users(): USERS.append(user) return pwd_file
def present(dest, username, password, crypt_scheme, create, check_mode): """ Ensures user is present Returns (msg, changed) """ if crypt_scheme in apache_hashes: context = htpasswd_context else: context = CryptContext(schemes = [ crypt_scheme ] + apache_hashes) if not os.path.exists(dest): if not create: raise ValueError('Destination %s does not exist' % dest) if check_mode: return ("Create %s" % dest, True) create_missing_directories(dest) if StrictVersion(passlib.__version__) >= StrictVersion('1.6'): ht = HtpasswdFile(dest, new=True, default_scheme=crypt_scheme, context=context) else: ht = HtpasswdFile(dest, autoload=False, default=crypt_scheme, context=context) if getattr(ht, 'set_password', None): ht.set_password(username, password) else: ht.update(username, password) ht.save() return ("Created %s and added %s" % (dest, username), True) else: if StrictVersion(passlib.__version__) >= StrictVersion('1.6'): ht = HtpasswdFile(dest, new=False, default_scheme=crypt_scheme, context=context) else: ht = HtpasswdFile(dest, default=crypt_scheme, context=context) found = None if getattr(ht, 'check_password', None): found = ht.check_password(username, password) else: found = ht.verify(username, password) if found: return ("%s already present" % username, False) else: if not check_mode: if getattr(ht, 'set_password', None): ht.set_password(username, password) else: ht.update(username, password) ht.save() return ("Add/update %s" % username, True)
def make_htpasswd(self, filename): ht = HtpasswdFile(path=filename, new=True) for username, password in self.users.items(): ht.set_password(username, password) ht.save()
class HtpasswdUsers(Component): implements(IUserAuthenticator) implements(IUserTranslator) implements(IUserStore) def __init__(self): config = self.get_component_config() if 'file' not in config: raise InsufficientConfiguration(missing='file', component=self.get_component_name()) self.htpasswd = HtpasswdFile(config['file']) def username_to_user(self, username): self.htpasswd.load_if_changed() if username in self.htpasswd.users(): return HtpasswdUser(self, username, username=username, full_name=username) def userid_to_user(self, userid): if userid is None or userid == '*': warnings.warn("You should not call this directly. Use cydra.get_user()", DeprecationWarning, stacklevel=2) return self.compmgr.get_user(userid='*') self.htpasswd.load_if_changed() if userid in self.htpasswd.users(): return HtpasswdUser(self, userid, username=userid, full_name=userid) else: # since the client was looking for a specific ID, # we return a dummy user object with empty data return User(self, userid, full_name='N/A') def groupid_to_group(self, groupid): pass def user_password(self, user, password): self.htpasswd.load_if_changed() return self.htpasswd.check_password(user.userid, password) def create_user(self, **kwargs): self.htpasswd.load_if_changed() userid = None if 'id' in kwargs: userid = kwargs['id'] elif 'username' in kwargs: userid = kwargs['username'] else: raise ValueError("No username/id specified") if userid in self.htpasswd.users(): raise ValueError("User with this id already exists") else: self.htpasswd.set_password(userid, hashlib.sha1(os.urandom(8)).hexdigest()) self.htpasswd.save() return userid
#! /usr/bin/env python from passlib.apache import HtpasswdFile ht = HtpasswdFile("/etc/pypiserver/htpasswd", new=True) ht.set_password("{{ username }}", "{{ password }}") ht.save()
class HtPasswdAuth(object): """Configure htpasswd based basic and token authentication.""" def __init__(self, app=None): """Boiler plate extension init with log_level being declared""" self.users = HtpasswdFile() self.app = app if app is not None: self.init_app(app) def init_app(self, app): """ Find and configure the user database from specified file """ app.config.setdefault('FLASK_AUTH_ALL', False) app.config.setdefault('FLASK_AUTH_REALM', 'Login Required') # Default set to bad file to trigger IOError app.config.setdefault('FLASK_HTPASSWD_PATH', '/^^^/^^^') # Load up user database try: self.load_users(app) except IOError: log.critical( 'No htpasswd file loaded, please set `FLASK_HTPASSWD`' 'or `FLASK_HTPASSWD_PATH` environment variable to a ' 'valid apache htpasswd file.' ) # Allow requiring auth for entire app, with pre request method @app.before_request def require_auth(): # pylint: disable=unused-variable """Pre request processing for enabling full app authentication.""" if not current_app.config['FLASK_AUTH_ALL']: return is_valid, user = self.authenticate() if not is_valid: return self.auth_failed() g.user = user def load_users(self, app): """ Load users from configured file. Args: app (flask.Flask): Flask application to load users from. Raises: IOError: If the configured htpasswd file does not exist. Returns: None """ self.users = HtpasswdFile( app.config['FLASK_HTPASSWD_PATH'] ) def check_basic_auth(self, username, password): """ This function is called to check if a username / password combination is valid via the htpasswd file. """ valid = self.users.check_password( username, password ) if not valid: log.warning('Invalid login from %s', username) valid = False return ( valid, username ) @staticmethod def get_signature(): """ Setup crypto sig. """ return Serializer(current_app.config['FLASK_SECRET']) def get_hashhash(self, username): """ Generate a digest of the htpasswd hash """ return hashlib.sha256( self.users.get_hash(username) ).hexdigest() def generate_token(self, username): """ assumes user exists in htpasswd file. Return the token for the given user by signing a token of the username and a hash of the htpasswd string. """ serializer = self.get_signature() return serializer.dumps( { 'username': username, 'hashhash': self.get_hashhash(username) } ).decode('UTF-8') def check_token_auth(self, token): """ Check to see who this is and if their token gets them into the system. """ serializer = self.get_signature() try: data = serializer.loads(token) except BadSignature: log.warning('Received bad token signature') return False, None if data['username'] not in self.users.users(): log.warning( 'Token auth signed message, but invalid user %s', data['username'] ) return False, None if data['hashhash'] != self.get_hashhash(data['username']): log.warning( 'Token and password do not match, %s ' 'needs to regenerate token', data['username'] ) return False, None return True, data['username'] @staticmethod def auth_failed(): """ Sends a 401 response that enables basic auth """ return Response( 'Could not verify your access level for that URL.\n' 'You have to login with proper credentials', 401, {'WWW-Authenticate': 'Basic realm="{0}"'.format( current_app.config['FLASK_AUTH_REALM'] )} ) def authenticate(self): """Authenticate user by any means and return either true or false. Args: Returns: tuple (is_valid, username): True is valid user, False if not """ basic_auth = request.authorization is_valid = False user = None if basic_auth: is_valid, user = self.check_basic_auth( basic_auth.username, basic_auth.password ) else: # Try token auth token = request.headers.get('Authorization', None) param_token = request.args.get('access_token') if token or param_token: if token: # slice the 'token ' piece of the header (following # github style): token = token[6:] else: # Grab it from query dict instead token = param_token log.debug('Received token: %s', token) is_valid, user = self.check_token_auth(token) return (is_valid, user) def required(self, func): """ Decorator function with basic and token authentication handler """ @wraps(func) def decorated(*args, **kwargs): """ Actual wrapper to run the auth checks. """ is_valid, user = self.authenticate() if not is_valid: return self.auth_failed() kwargs['user'] = user return func(*args, **kwargs) return decorated
def __init__(self, app=None): """Boiler plate extension init with log_level being declared""" self.users = HtpasswdFile() self.app = app if app is not None: self.init_app(app)
def __init__(self, filename): self._ht = HtpasswdFile(filename)