4
\$\begingroup\$

I've written a couple of functions to check if a consumer of the API should be authenticated to use it or not.

Have I done anything blatantly wrong here?

Config

API_CONSUMERS = [{'name': 'localhost',
 'host': '12.0.0.1:5000',
 'api_key': 'Ahth2ea5Ohngoop5'},
 {'name': 'localhost2',
 'host': '127.0.0.1:5001',
 'api_key': 'Ahth2ea5Ohngoop6'}]

Exceptions

class BaseException(Exception):
 def __init__(self, logger, *args, **kwargs):
 super(BaseException, self).__init__(*args, **kwargs)
 logger.info(self.message)
class UnknownHostException(BaseException):
 pass
class MissingHashException(BaseException):
 pass
class HashMismatchException(BaseException):
 pass

Authentication methods

import hashlib
from flask import request
from services.exceptions import (UnknownHostException, MissingHashException,
 HashMismatchException)
def is_authenticated(app):
 """
 Checks that the consumers host is valid, the request has a hash and the
 hash is the same when we excrypt the data with that hosts api key
 Arguments:
 app -- instance of the application
 """
 consumers = app.config.get('API_CONSUMERS')
 host = request.host
 try:
 api_key = next(d['api_key'] for d in consumers if d['host'] == host)
 except StopIteration:
 raise UnknownHostException(
 app.logger, 'Authentication failed: Unknown Host (' + host + ')')
 if not request.headers.get('hash'):
 raise MissingHashException(
 app.logger, 'Authentication failed: Missing Hash (' + host + ')')
 hash = calculate_hash(request.method, api_key)
 if hash != request.headers.get('hash'):
 raise HashMismatchException(
 app.logger, 'Authentication failed: Hash Mismatch (' + host + ')')
 return True
def calculate_hash(method, api_key):
 """
 Calculates the hash using either the url or the request content,
 plus the hosts api key
 Arguments:
 method -- request method
 api_key -- api key for this host
 """
 if request.method == 'GET':
 data_to_hash = request.base_url + '?' + request.query_string
 elif request.method == 'POST':
 data_to_hash = request.data
 data_to_hash += api_key
 return hashlib.sha1(data_to_hash).hexdigest()
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Dec 19, 2012 at 19:10
\$\endgroup\$
0

2 Answers 2

4
\$\begingroup\$

Building on @Drewverlee's answer, I would consider renaming BaseException to APIException, or something of the like.

Also, I don't think passing app as an argument is best practice, I would recommend using the function as a decorator on your endpoints instead:

# Your imports
from application import app # Or whatever your non-relative reference is
def is_authenticated(func):
 def func_wrapper():
 # Your code here without the original def call
 return func_wrapper

You can then use this on each endpoint, adding the @is_authenticated decorator, to ensure the app is properly authenticated.

answered Jul 26, 2016 at 23:41
\$\endgroup\$
6
\$\begingroup\$

Exception itself actually inherits from a class called BaseException so:

class BaseException(Exception):

Seems backwards.

answered Dec 21, 2012 at 22:50
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.