# Copyright 2015 Vinicius Chiele. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Provides classes for authentication.""" import base64 from flask import request from werkzeug.http import bytes_to_wsgi, wsgi_to_bytes def get_authorization_header(): """ Return request's 'Authorization:' header as a two-tuple of (type, info). """ header = request.environ.get('HTTP_AUTHORIZATION') if not header: return None header = wsgi_to_bytes(header) try: auth_type, auth_info = header.split(None, 1) auth_type = auth_type.lower() except ValueError: return None return auth_type, auth_info class Authorization(dict): """ A class to hold the authorization data. :param str auth_type: The authorization type. e.g: basic, bearer. """ def __init__(self, auth_type, **kwargs): super(Authorization, self).__init__(**kwargs) self.auth_type = auth_type class HTTPAuth(object): """ A base class from which all authentication classes should inherit. """ def get_authorization(self): """ Get the authorization header. :return Authentication: The authentication data or None if it is not present or invalid. """ raise NotImplemented() def get_authenticate_header(self): """ Return the value of `WWW-Authenticate` header in a `401 Unauthenticated` response. """ pass class HTTPBasicAuth(HTTPAuth): """ HTTP Basic authentication. """ www_authenticate_realm = 'Authentication Required' def get_authorization(self): """ Get the username and password for Basic authentication header. :return Authentication: The authentication data or None if it is not present or invalid. """ auth = get_authorization_header() if not auth: return None auth_type, auth_info = auth if auth_type != b'basic': return None try: username, password = base64.b64decode(auth_info).split(b':', 1) except Exception: return None return Authorization('basic', username=bytes_to_wsgi(username), password=bytes_to_wsgi(password)) def get_authenticate_header(self): """ Return the value of `WWW-Authenticate` header in a `401 Unauthenticated` response. """ return 'Basic realm="%s"' % self.www_authenticate_realm