Source code for auth

"""
Contains declarations for HTTP authorization, needed to be put here to avoid a
circular import where :mod:`api_server` imports
:class:`api_views.users.UserContainer`, but
:class:`api_views.users.UserContaner` requires an ``auth`` object
declared in :mod:`api_server`
"""
from uuid import UUID
from flask import g
from flask.ext.httpauth import HTTPBasicAuth
from config import default_config as conf
from database import User, Token, ContextManagedSession

__author__ = 'Michal Kononenko'
auth = HTTPBasicAuth()
database_session = ContextManagedSession(bind=conf.DATABASE_ENGINE)


@auth.verify_password
[docs]def verify_password(username_or_token, password=None): """ Callback function for :func:`flask.ext.httpauth.HTTPBasicAuth.verify_password`, used to verify both username and password authentication, as well as authentication tokens. In order to authenticate, the user must use base64 encoding, encode a string of the form ``username:password``, and submit the encoded string in the request's Authorization_. header. Alternatively, the user can encode their token in base64, and submit this in their Authorization_. header. In this case, the incoming password will be ``None``. .. warning:: Basic Authentication, unless done over SSL_. **IS NOT A SECURE FORM** ** OF AUTHENTICATION**, as **ANYONE** can intercept an HTTP request, and decode the information in the Authorization header. This will be solved in two ways - Any production deployment of this API will be done using SSL - HMAC-SHA256_. authentication will be supported, although this is currently out of scope for the Christmas Release of this API :param str username_or_token: The username or token of the user attempting to authenticate into the API :param str password: The password or token to be used to authenticate into the API. If no password is supplied, this value will be ``None``. :return: True if the password or token is correct, False if otherwise :rtype bool: .. _Authorization: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.8 .. _SSL: https://en.wikipedia.org/wiki/Transport_Layer_Security .. _HMAC-SHA256: https://en.wikipedia.org/wiki/Hash-based_message_authentication_code """ try: UUID(hex=username_or_token) except (TypeError, ValueError): return _verify_user(username_or_token, password) with database_session() as session: token = session.query( Token ).filter_by( token_hash=Token.hash_token(username_or_token) ).first() if token is None: return _verify_user(username_or_token, password) if token.verify_token(username_or_token): g.user = token.owner return True else: return False
[docs]def _verify_user(username, password): """ Check if the username matches the user. If it does, write the user to :meth:`Flask.g` and return ``True``, else return ``False`` :param str username: The name of the user to validate :param str password: The password to validate :return: ``True`` if the user authenticated and ``False`` if not """ with database_session() as session: user = session.query( User ).filter_by( username=username ).first() if user is None: return False if user.verify_password(password): g.user = user return True