Source code for lightmlrestapi.mlapp.authfiction
"""
Authentification part.
:githublink:`%|py|5`
"""
import base64
import falcon
from ..args import encrypt_password, load_passwords
[docs]class AuthMiddleware:
"""
Authentification. The name and secret comes from
a file. The file must store encrypted password.
:githublink:`%|py|14`
"""
help_url = "http://www.xavierdupre.fr/app/lightmlrestapi/helpsphinx/tutorial/first_rest_api.html"
[docs] def __init__(self, source, algo="sha224"):
"""
:param source: filename or dataframe for encrypted password
:param algo: algorithm used to hash the passwords
:githublink:`%|py|22`
"""
if source is None:
raise ValueError("source cannot be empty")
self.allowed = load_passwords(source)
self.algo = algo
self.auth_header_prefix = 'Basic'
[docs] def parse_auth_token_from_request(self, auth_header):
"""
Parses and returns Auth token from the request header. Raises
`falcon.HTTPUnauthoried exception` with proper error message
:githublink:`%|py|33`
"""
if not auth_header:
raise falcon.HTTPUnauthorized(
title='401 Unauthorized', description='Missing Authorization Header')
parts = auth_header.split()
if parts[0].lower() != self.auth_header_prefix.lower():
raise falcon.HTTPUnauthorized(title='401 Unauthorized',
description='Invalid Authorization Header: '
'Must start with {0}'.format(self.auth_header_prefix))
if len(parts) == 1:
raise falcon.HTTPUnauthorized(
title='401 Unauthorized',
description='Invalid Authorization Header: Token Missing')
if len(parts) > 2:
raise falcon.HTTPUnauthorized(
title='401 Unauthorized',
description='Invalid Authorization Header: Contains extra content')
return parts[1]
[docs] def process_request(self, req, resp):
"""
Processes an authentification request.
:param req: request
:param resp: unused
:githublink:`%|py|63`
"""
if req.scheme.lower() != 'https':
raise falcon.HTTPBadRequest(title='HTTPS Required',
description=('All requests must be performed via the HTTPS protocol. '
'Please switch to HTTPS and try again.'))
auth = req.get_header('Authorization')
token = self.parse_auth_token_from_request(auth_header=auth)
try:
token = base64.b64decode(token).decode('utf-8')
except Exception:
raise falcon.HTTPUnauthorized(title='401 Unauthorized',
description='Invalid Authorization Header: Unable to decode credentials (1)')
try:
username, password = token.split(':', 1)
except ValueError:
raise falcon.HTTPUnauthorized(
title='401 Unauthorized',
description='Invalid Authorization: Unable to decode credentials (2)')
if not self._token_is_valid(username, password):
raise falcon.HTTPUnauthorized(
"Authentication failed for '{0}'".format(username))
[docs] def _token_is_valid(self, username, password):
"""
Decides if it is valid or not.
:githublink:`%|py|91`
"""
if username not in self.allowed:
return False
enc = encrypt_password(password, algo=self.algo)
return self.allowed[username] == enc