We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
API keys should be supported in the HTTP headers
Currently it seems that all API calls must include the `api_key` in the query string. Ideally the HTTP headers could also be used (e.g. `Authorization: Key XXXX` or `X-Api-Key`) so that Web server logs don't log the API key in the clear.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `redash/authentication.py`
Content:
```
1 import hashlib
2 import hmac
3 import time
4 import logging
5 
6 from flask.ext.login import LoginManager
7 from flask.ext.login import user_logged_in
8 
9 from redash import models, settings, google_oauth, saml_auth
10 from redash.tasks import record_event
11 
12 login_manager = LoginManager()
13 logger = logging.getLogger('authentication')
14 
15 
16 def sign(key, path, expires):
17     if not key:
18         return None
19 
20     h = hmac.new(str(key), msg=path, digestmod=hashlib.sha1)
21     h.update(str(expires))
22 
23     return h.hexdigest()
24 
25 
26 @login_manager.user_loader
27 def load_user(user_id):
28     return models.User.get_by_id(user_id)
29 
30 
31 def hmac_load_user_from_request(request):
32     signature = request.args.get('signature')
33     expires = float(request.args.get('expires') or 0)
34     query_id = request.view_args.get('query_id', None)
35     user_id = request.args.get('user_id', None)
36 
37     # TODO: 3600 should be a setting
38     if signature and time.time() < expires <= time.time() + 3600:
39         if user_id:
40             user = models.User.get_by_id(user_id)
41             calculated_signature = sign(user.api_key, request.path, expires)
42 
43             if user.api_key and signature == calculated_signature:
44                 return user
45 
46         if query_id:
47             query = models.Query.get(models.Query.id == query_id)
48             calculated_signature = sign(query.api_key, request.path, expires)
49 
50             if query.api_key and signature == calculated_signature:
51                 return models.ApiUser(query.api_key)
52 
53     return None
54 
55 def get_user_from_api_key(api_key, query_id):
56     if not api_key:
57         return None
58 
59     user = None
60     try:
61         user = models.User.get_by_api_key(api_key)
62     except models.User.DoesNotExist:
63         if query_id:
64             query = models.Query.get_by_id(query_id)
65             if query and query.api_key == api_key:
66                 user = models.ApiUser(api_key)
67 
68     return user
69 
70 def api_key_load_user_from_request(request):
71     api_key = request.args.get('api_key', None)
72     query_id = request.view_args.get('query_id', None)
73 
74     user = get_user_from_api_key(api_key, query_id)
75     return user
76 
77 
78 def log_user_logged_in(app, user):
79     event = {
80         'user_id': user.id,
81         'action': 'login',
82         'object_type': 'redash',
83         'timestamp': int(time.time()),
84     }
85 
86     record_event.delay(event)
87 
88 
89 def setup_authentication(app):
90     login_manager.init_app(app)
91     login_manager.anonymous_user = models.AnonymousUser
92     login_manager.login_view = 'login'
93     app.secret_key = settings.COOKIE_SECRET
94     app.register_blueprint(google_oauth.blueprint)
95     app.register_blueprint(saml_auth.blueprint)
96 
97     user_logged_in.connect(log_user_logged_in)
98 
99     if settings.AUTH_TYPE == 'hmac':
100         login_manager.request_loader(hmac_load_user_from_request)
101     elif settings.AUTH_TYPE == 'api_key':
102         login_manager.request_loader(api_key_load_user_from_request)
103     else:
104         logger.warning("Unknown authentication type ({}). Using default (HMAC).".format(settings.AUTH_TYPE))
105         login_manager.request_loader(hmac_load_user_from_request)
106 
107 
108
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/redash/authentication.py b/redash/authentication.py
--- a/redash/authentication.py
+++ b/redash/authentication.py
@@ -52,6 +52,7 @@
 
     return None
 
+
 def get_user_from_api_key(api_key, query_id):
     if not api_key:
         return None
@@ -67,8 +68,19 @@
 
     return user
 
-def api_key_load_user_from_request(request):
+
+def get_api_key_from_request(request):
     api_key = request.args.get('api_key', None)
+
+    if api_key is None and request.headers.get('Authorization'):
+        auth_header = request.headers.get('Authorization')
+        api_key = auth_header.replace('Key ', '', 1)
+
+    return api_key
+
+
+def api_key_load_user_from_request(request):
+    api_key = get_api_key_from_request(request)
     query_id = request.view_args.get('query_id', None)
 
     user = get_user_from_api_key(api_key, query_id)

{"golden_diff": "diff --git a/redash/authentication.py b/redash/authentication.py\n--- a/redash/authentication.py\n+++ b/redash/authentication.py\n@@ -52,6 +52,7 @@\n \n     return None\n \n+\n def get_user_from_api_key(api_key, query_id):\n     if not api_key:\n         return None\n@@ -67,8 +68,19 @@\n \n     return user\n \n-def api_key_load_user_from_request(request):\n+\n+def get_api_key_from_request(request):\n     api_key = request.args.get('api_key', None)\n+\n+    if api_key is None and request.headers.get('Authorization'):\n+        auth_header = request.headers.get('Authorization')\n+        api_key = auth_header.replace('Key ', '', 1)\n+\n+    return api_key\n+\n+\n+def api_key_load_user_from_request(request):\n+    api_key = get_api_key_from_request(request)\n     query_id = request.view_args.get('query_id', None)\n \n     user = get_user_from_api_key(api_key, query_id)\n", "issue": "API keys should be supported in the HTTP headers\nCurrently it seems that all API calls must include the `api_key` in the query string. Ideally the HTTP headers could also be used (e.g. `Authorization: Key XXXX` or `X-Api-Key`) so that Web server logs don't log the API key in the clear.\n\n", "before_files": [{"content": "import hashlib\nimport hmac\nimport time\nimport logging\n\nfrom flask.ext.login import LoginManager\nfrom flask.ext.login import user_logged_in\n\nfrom redash import models, settings, google_oauth, saml_auth\nfrom redash.tasks import record_event\n\nlogin_manager = LoginManager()\nlogger = logging.getLogger('authentication')\n\n\ndef sign(key, path, expires):\n    if not key:\n        return None\n\n    h = hmac.new(str(key), msg=path, digestmod=hashlib.sha1)\n    h.update(str(expires))\n\n    return h.hexdigest()\n\n\n@login_manager.user_loader\ndef load_user(user_id):\n    return models.User.get_by_id(user_id)\n\n\ndef hmac_load_user_from_request(request):\n    signature = request.args.get('signature')\n    expires = float(request.args.get('expires') or 0)\n    query_id = request.view_args.get('query_id', None)\n    user_id = request.args.get('user_id', None)\n\n    # TODO: 3600 should be a setting\n    if signature and time.time() < expires <= time.time() + 3600:\n        if user_id:\n            user = models.User.get_by_id(user_id)\n            calculated_signature = sign(user.api_key, request.path, expires)\n\n            if user.api_key and signature == calculated_signature:\n                return user\n\n        if query_id:\n            query = models.Query.get(models.Query.id == query_id)\n            calculated_signature = sign(query.api_key, request.path, expires)\n\n            if query.api_key and signature == calculated_signature:\n                return models.ApiUser(query.api_key)\n\n    return None\n\ndef get_user_from_api_key(api_key, query_id):\n    if not api_key:\n        return None\n\n    user = None\n    try:\n        user = models.User.get_by_api_key(api_key)\n    except models.User.DoesNotExist:\n        if query_id:\n            query = models.Query.get_by_id(query_id)\n            if query and query.api_key == api_key:\n                user = models.ApiUser(api_key)\n\n    return user\n\ndef api_key_load_user_from_request(request):\n    api_key = request.args.get('api_key', None)\n    query_id = request.view_args.get('query_id', None)\n\n    user = get_user_from_api_key(api_key, query_id)\n    return user\n\n\ndef log_user_logged_in(app, user):\n    event = {\n        'user_id': user.id,\n        'action': 'login',\n        'object_type': 'redash',\n        'timestamp': int(time.time()),\n    }\n\n    record_event.delay(event)\n\n\ndef setup_authentication(app):\n    login_manager.init_app(app)\n    login_manager.anonymous_user = models.AnonymousUser\n    login_manager.login_view = 'login'\n    app.secret_key = settings.COOKIE_SECRET\n    app.register_blueprint(google_oauth.blueprint)\n    app.register_blueprint(saml_auth.blueprint)\n\n    user_logged_in.connect(log_user_logged_in)\n\n    if settings.AUTH_TYPE == 'hmac':\n        login_manager.request_loader(hmac_load_user_from_request)\n    elif settings.AUTH_TYPE == 'api_key':\n        login_manager.request_loader(api_key_load_user_from_request)\n    else:\n        logger.warning(\"Unknown authentication type ({}). Using default (HMAC).\".format(settings.AUTH_TYPE))\n        login_manager.request_loader(hmac_load_user_from_request)\n\n\n", "path": "redash/authentication.py"}], "after_files": [{"content": "import hashlib\nimport hmac\nimport time\nimport logging\n\nfrom flask.ext.login import LoginManager\nfrom flask.ext.login import user_logged_in\n\nfrom redash import models, settings, google_oauth, saml_auth\nfrom redash.tasks import record_event\n\nlogin_manager = LoginManager()\nlogger = logging.getLogger('authentication')\n\n\ndef sign(key, path, expires):\n    if not key:\n        return None\n\n    h = hmac.new(str(key), msg=path, digestmod=hashlib.sha1)\n    h.update(str(expires))\n\n    return h.hexdigest()\n\n\n@login_manager.user_loader\ndef load_user(user_id):\n    return models.User.get_by_id(user_id)\n\n\ndef hmac_load_user_from_request(request):\n    signature = request.args.get('signature')\n    expires = float(request.args.get('expires') or 0)\n    query_id = request.view_args.get('query_id', None)\n    user_id = request.args.get('user_id', None)\n\n    # TODO: 3600 should be a setting\n    if signature and time.time() < expires <= time.time() + 3600:\n        if user_id:\n            user = models.User.get_by_id(user_id)\n            calculated_signature = sign(user.api_key, request.path, expires)\n\n            if user.api_key and signature == calculated_signature:\n                return user\n\n        if query_id:\n            query = models.Query.get(models.Query.id == query_id)\n            calculated_signature = sign(query.api_key, request.path, expires)\n\n            if query.api_key and signature == calculated_signature:\n                return models.ApiUser(query.api_key)\n\n    return None\n\n\ndef get_user_from_api_key(api_key, query_id):\n    if not api_key:\n        return None\n\n    user = None\n    try:\n        user = models.User.get_by_api_key(api_key)\n    except models.User.DoesNotExist:\n        if query_id:\n            query = models.Query.get_by_id(query_id)\n            if query and query.api_key == api_key:\n                user = models.ApiUser(api_key)\n\n    return user\n\n\ndef get_api_key_from_request(request):\n    api_key = request.args.get('api_key', None)\n\n    if api_key is None and request.headers.get('Authorization'):\n        auth_header = request.headers.get('Authorization')\n        api_key = auth_header.replace('Key ', '', 1)\n\n    return api_key\n\n\ndef api_key_load_user_from_request(request):\n    api_key = get_api_key_from_request(request)\n    query_id = request.view_args.get('query_id', None)\n\n    user = get_user_from_api_key(api_key, query_id)\n    return user\n\n\ndef log_user_logged_in(app, user):\n    event = {\n        'user_id': user.id,\n        'action': 'login',\n        'object_type': 'redash',\n        'timestamp': int(time.time()),\n    }\n\n    record_event.delay(event)\n\n\ndef setup_authentication(app):\n    login_manager.init_app(app)\n    login_manager.anonymous_user = models.AnonymousUser\n    login_manager.login_view = 'login'\n    app.secret_key = settings.COOKIE_SECRET\n    app.register_blueprint(google_oauth.blueprint)\n    app.register_blueprint(saml_auth.blueprint)\n\n    user_logged_in.connect(log_user_logged_in)\n\n    if settings.AUTH_TYPE == 'hmac':\n        login_manager.request_loader(hmac_load_user_from_request)\n    elif settings.AUTH_TYPE == 'api_key':\n        login_manager.request_loader(api_key_load_user_from_request)\n    else:\n        logger.warning(\"Unknown authentication type ({}). Using default (HMAC).\".format(settings.AUTH_TYPE))\n        login_manager.request_loader(hmac_load_user_from_request)\n\n\n", "path": "redash/authentication.py"}]}