We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
API Key authentication should take precedence over cookies
Currently when you're logged in as a user, you can't use embeds or shared dashboards for which you do not have access -- even if you provide the API key. This is because the current user is being defined by the session cookie and the API key is being ignored.

We need to change this behavior so the API key takes precedence. From a quick look at [Flask-Login](https://flask-login.readthedocs.io)'s documentation, it seems that it calls `user_loader` first and only if this fails will try the `requets_loader`.

Unless this is configurable, we might need to change `user_loader` to always return `None` and implement our own logic in `request_loader`.

--- 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/__init__.py`
Content:
```
1 import hashlib
2 import hmac
3 import logging
4 import time
5 from urlparse import urlsplit, urlunsplit
6 
7 from flask import jsonify, redirect, request, url_for
8 from flask_login import LoginManager, login_user, logout_user, user_logged_in
9 from redash import models, settings
10 from redash.authentication import jwt_auth
11 from redash.authentication.org_resolving import current_org
12 from redash.settings.organization import settings as org_settings
13 from redash.tasks import record_event
14 from sqlalchemy.orm.exc import NoResultFound
15 from werkzeug.exceptions import Unauthorized
16 
17 login_manager = LoginManager()
18 logger = logging.getLogger('authentication')
19 
20 
21 def get_login_url(external=False, next="/"):
22     if settings.MULTI_ORG and current_org == None:
23         login_url = '/'
24     elif settings.MULTI_ORG:
25         login_url = url_for('redash.login', org_slug=current_org.slug, next=next, _external=external)
26     else:
27         login_url = url_for('redash.login', next=next, _external=external)
28 
29     return login_url
30 
31 
32 def sign(key, path, expires):
33     if not key:
34         return None
35 
36     h = hmac.new(str(key), msg=path, digestmod=hashlib.sha1)
37     h.update(str(expires))
38 
39     return h.hexdigest()
40 
41 
42 @login_manager.user_loader
43 def load_user(user_id_with_identity):
44     org = current_org._get_current_object()
45 
46     try:
47         user_id, _ = user_id_with_identity.split("-")
48         user = models.User.get_by_id_and_org(user_id, org)
49         if user.is_disabled or user.get_id() != user_id_with_identity:
50             return None
51 
52         return user
53     except (models.NoResultFound, ValueError, AttributeError):
54         return None
55 
56 
57 def request_loader(request):
58     user = None
59     if settings.AUTH_TYPE == 'hmac':
60         user = hmac_load_user_from_request(request)
61     elif settings.AUTH_TYPE == 'api_key':
62         user = api_key_load_user_from_request(request)
63     else:
64         logger.warning("Unknown authentication type ({}). Using default (HMAC).".format(settings.AUTH_TYPE))
65         user = hmac_load_user_from_request(request)
66 
67     if org_settings['auth_jwt_login_enabled'] and user is None:
68         user = jwt_token_load_user_from_request(request)
69     return user
70 
71 
72 def hmac_load_user_from_request(request):
73     signature = request.args.get('signature')
74     expires = float(request.args.get('expires') or 0)
75     query_id = request.view_args.get('query_id', None)
76     user_id = request.args.get('user_id', None)
77 
78     # TODO: 3600 should be a setting
79     if signature and time.time() < expires <= time.time() + 3600:
80         if user_id:
81             user = models.User.query.get(user_id)
82             calculated_signature = sign(user.api_key, request.path, expires)
83 
84             if user.api_key and signature == calculated_signature:
85                 return user
86 
87         if query_id:
88             query = models.Query.query.filter(models.Query.id == query_id).one()
89             calculated_signature = sign(query.api_key, request.path, expires)
90 
91             if query.api_key and signature == calculated_signature:
92                 return models.ApiUser(query.api_key, query.org, query.groups.keys(), name="ApiKey: Query {}".format(query.id))
93 
94     return None
95 
96 
97 def get_user_from_api_key(api_key, query_id):
98     if not api_key:
99         return None
100 
101     user = None
102 
103     # TODO: once we switch all api key storage into the ApiKey model, this code will be much simplified
104     org = current_org._get_current_object()
105     try:
106         user = models.User.get_by_api_key_and_org(api_key, org)
107         if user.is_disabled:
108             user = None
109     except models.NoResultFound:
110         try:
111             api_key = models.ApiKey.get_by_api_key(api_key)
112             user = models.ApiUser(api_key, api_key.org, [])
113         except models.NoResultFound:
114             if query_id:
115                 query = models.Query.get_by_id_and_org(query_id, org)
116                 if query and query.api_key == api_key:
117                     user = models.ApiUser(api_key, query.org, query.groups.keys(), name="ApiKey: Query {}".format(query.id))
118 
119     return user
120 
121 
122 def get_api_key_from_request(request):
123     api_key = request.args.get('api_key', None)
124 
125     if api_key is not None:
126         return api_key
127 
128     if request.headers.get('Authorization'):
129         auth_header = request.headers.get('Authorization')
130         api_key = auth_header.replace('Key ', '', 1)
131     elif request.view_args is not None and request.view_args.get('token'):
132         api_key = request.view_args['token']
133 
134     return api_key
135 
136 
137 def api_key_load_user_from_request(request):
138     api_key = get_api_key_from_request(request)
139     if request.view_args is not None:
140         query_id = request.view_args.get('query_id', None)
141         user = get_user_from_api_key(api_key, query_id)
142     else:
143         user = None
144 
145     return user
146 
147 
148 def jwt_token_load_user_from_request(request):
149     org = current_org._get_current_object()
150 
151     payload = None
152 
153     if org_settings['auth_jwt_auth_cookie_name']:
154         jwt_token = request.cookies.get(org_settings['auth_jwt_auth_cookie_name'], None)
155     elif org_settings['auth_jwt_auth_header_name']:
156         jwt_token = request.headers.get(org_settings['auth_jwt_auth_header_name'], None)
157     else:
158         return None
159 
160     if jwt_token:
161         payload, token_is_valid = jwt_auth.verify_jwt_token(
162             jwt_token,
163             expected_issuer=org_settings['auth_jwt_auth_issuer'],
164             expected_audience=org_settings['auth_jwt_auth_audience'],
165             algorithms=org_settings['auth_jwt_auth_algorithms'],
166             public_certs_url=org_settings['auth_jwt_auth_public_certs_url'],
167         )
168         if not token_is_valid:
169             raise Unauthorized('Invalid JWT token')
170 
171     if not payload:
172         return
173 
174     try:
175         user = models.User.get_by_email_and_org(payload['email'], org)
176     except models.NoResultFound:
177         user = create_and_login_user(current_org, payload['email'], payload['email'])
178 
179     return user
180 
181 
182 def log_user_logged_in(app, user):
183     event = {
184         'org_id': user.org_id,
185         'user_id': user.id,
186         'action': 'login',
187         'object_type': 'redash',
188         'timestamp': int(time.time()),
189         'user_agent': request.user_agent.string,
190         'ip': request.remote_addr
191     }
192 
193     record_event.delay(event)
194 
195 
196 @login_manager.unauthorized_handler
197 def redirect_to_login():
198     if request.is_xhr or '/api/' in request.path:
199         response = jsonify({'message': "Couldn't find resource. Please login and try again."})
200         response.status_code = 404
201         return response
202 
203     login_url = get_login_url(next=request.url, external=False)
204 
205     return redirect(login_url)
206 
207 
208 def logout_and_redirect_to_index():
209     logout_user()
210 
211     if settings.MULTI_ORG and current_org == None:
212         index_url = '/'
213     elif settings.MULTI_ORG:
214         index_url = url_for('redash.index', org_slug=current_org.slug, _external=False)
215     else:
216         index_url = url_for('redash.index', _external=False)
217 
218     return redirect(index_url)
219 
220 
221 def init_app(app):
222     from redash.authentication import google_oauth, saml_auth, remote_user_auth, ldap_auth
223 
224     login_manager.init_app(app)
225     login_manager.anonymous_user = models.AnonymousUser
226 
227     app.register_blueprint(google_oauth.blueprint)
228     app.register_blueprint(saml_auth.blueprint)
229     app.register_blueprint(remote_user_auth.blueprint)
230     app.register_blueprint(ldap_auth.blueprint)
231 
232     user_logged_in.connect(log_user_logged_in)
233     login_manager.request_loader(request_loader)
234 
235 
236 def create_and_login_user(org, name, email, picture=None):
237     try:
238         user_object = models.User.get_by_email_and_org(email, org)
239         if user_object.is_disabled:
240             return None
241         if user_object.is_invitation_pending:
242             user_object.is_invitation_pending = False
243             models.db.session.commit()
244         if user_object.name != name:
245             logger.debug("Updating user name (%r -> %r)", user_object.name, name)
246             user_object.name = name
247             models.db.session.commit()
248     except NoResultFound:
249         logger.debug("Creating user object (%r)", name)
250         user_object = models.User(org=org, name=name, email=email, is_invitation_pending=False,
251                                   _profile_image_url=picture, group_ids=[org.default_group.id])
252         models.db.session.add(user_object)
253         models.db.session.commit()
254 
255     login_user(user_object, remember=True)
256 
257     return user_object
258 
259 
260 def get_next_path(unsafe_next_path):
261     if not unsafe_next_path:
262         return ''
263 
264     # Preventing open redirection attacks
265     parts = list(urlsplit(unsafe_next_path))
266     parts[0] = ''  # clear scheme
267     parts[1] = ''  # clear netloc
268     safe_next_path = urlunsplit(parts)
269 
270     return safe_next_path
271
```
--- 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/__init__.py b/redash/authentication/__init__.py
--- a/redash/authentication/__init__.py
+++ b/redash/authentication/__init__.py
@@ -41,6 +41,10 @@
 
 @login_manager.user_loader
 def load_user(user_id_with_identity):
+    user = api_key_load_user_from_request(request)
+    if user:
+        return user
+
     org = current_org._get_current_object()
 
     try:

{"golden_diff": "diff --git a/redash/authentication/__init__.py b/redash/authentication/__init__.py\n--- a/redash/authentication/__init__.py\n+++ b/redash/authentication/__init__.py\n@@ -41,6 +41,10 @@\n \n @login_manager.user_loader\n def load_user(user_id_with_identity):\n+    user = api_key_load_user_from_request(request)\n+    if user:\n+        return user\n+\n     org = current_org._get_current_object()\n \n     try:\n", "issue": "API Key authentication should take precedence over cookies\nCurrently when you're logged in as a user, you can't use embeds or shared dashboards for which you do not have access -- even if you provide the API key. This is because the current user is being defined by the session cookie and the API key is being ignored.\r\n\r\nWe need to change this behavior so the API key takes precedence. From a quick look at [Flask-Login](https://flask-login.readthedocs.io)'s documentation, it seems that it calls `user_loader` first and only if this fails will try the `requets_loader`.\r\n\r\nUnless this is configurable, we might need to change `user_loader` to always return `None` and implement our own logic in `request_loader`.\n", "before_files": [{"content": "import hashlib\nimport hmac\nimport logging\nimport time\nfrom urlparse import urlsplit, urlunsplit\n\nfrom flask import jsonify, redirect, request, url_for\nfrom flask_login import LoginManager, login_user, logout_user, user_logged_in\nfrom redash import models, settings\nfrom redash.authentication import jwt_auth\nfrom redash.authentication.org_resolving import current_org\nfrom redash.settings.organization import settings as org_settings\nfrom redash.tasks import record_event\nfrom sqlalchemy.orm.exc import NoResultFound\nfrom werkzeug.exceptions import Unauthorized\n\nlogin_manager = LoginManager()\nlogger = logging.getLogger('authentication')\n\n\ndef get_login_url(external=False, next=\"/\"):\n    if settings.MULTI_ORG and current_org == None:\n        login_url = '/'\n    elif settings.MULTI_ORG:\n        login_url = url_for('redash.login', org_slug=current_org.slug, next=next, _external=external)\n    else:\n        login_url = url_for('redash.login', next=next, _external=external)\n\n    return login_url\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_with_identity):\n    org = current_org._get_current_object()\n\n    try:\n        user_id, _ = user_id_with_identity.split(\"-\")\n        user = models.User.get_by_id_and_org(user_id, org)\n        if user.is_disabled or user.get_id() != user_id_with_identity:\n            return None\n\n        return user\n    except (models.NoResultFound, ValueError, AttributeError):\n        return None\n\n\ndef request_loader(request):\n    user = None\n    if settings.AUTH_TYPE == 'hmac':\n        user = hmac_load_user_from_request(request)\n    elif settings.AUTH_TYPE == 'api_key':\n        user = api_key_load_user_from_request(request)\n    else:\n        logger.warning(\"Unknown authentication type ({}). Using default (HMAC).\".format(settings.AUTH_TYPE))\n        user = hmac_load_user_from_request(request)\n\n    if org_settings['auth_jwt_login_enabled'] and user is None:\n        user = jwt_token_load_user_from_request(request)\n    return user\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.query.get(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.query.filter(models.Query.id == query_id).one()\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, query.org, query.groups.keys(), name=\"ApiKey: Query {}\".format(query.id))\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\n    # TODO: once we switch all api key storage into the ApiKey model, this code will be much simplified\n    org = current_org._get_current_object()\n    try:\n        user = models.User.get_by_api_key_and_org(api_key, org)\n        if user.is_disabled:\n            user = None\n    except models.NoResultFound:\n        try:\n            api_key = models.ApiKey.get_by_api_key(api_key)\n            user = models.ApiUser(api_key, api_key.org, [])\n        except models.NoResultFound:\n            if query_id:\n                query = models.Query.get_by_id_and_org(query_id, org)\n                if query and query.api_key == api_key:\n                    user = models.ApiUser(api_key, query.org, query.groups.keys(), name=\"ApiKey: Query {}\".format(query.id))\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 not None:\n        return api_key\n\n    if request.headers.get('Authorization'):\n        auth_header = request.headers.get('Authorization')\n        api_key = auth_header.replace('Key ', '', 1)\n    elif request.view_args is not None and request.view_args.get('token'):\n        api_key = request.view_args['token']\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    if request.view_args is not None:\n        query_id = request.view_args.get('query_id', None)\n        user = get_user_from_api_key(api_key, query_id)\n    else:\n        user = None\n\n    return user\n\n\ndef jwt_token_load_user_from_request(request):\n    org = current_org._get_current_object()\n\n    payload = None\n\n    if org_settings['auth_jwt_auth_cookie_name']:\n        jwt_token = request.cookies.get(org_settings['auth_jwt_auth_cookie_name'], None)\n    elif org_settings['auth_jwt_auth_header_name']:\n        jwt_token = request.headers.get(org_settings['auth_jwt_auth_header_name'], None)\n    else:\n        return None\n\n    if jwt_token:\n        payload, token_is_valid = jwt_auth.verify_jwt_token(\n            jwt_token,\n            expected_issuer=org_settings['auth_jwt_auth_issuer'],\n            expected_audience=org_settings['auth_jwt_auth_audience'],\n            algorithms=org_settings['auth_jwt_auth_algorithms'],\n            public_certs_url=org_settings['auth_jwt_auth_public_certs_url'],\n        )\n        if not token_is_valid:\n            raise Unauthorized('Invalid JWT token')\n\n    if not payload:\n        return\n\n    try:\n        user = models.User.get_by_email_and_org(payload['email'], org)\n    except models.NoResultFound:\n        user = create_and_login_user(current_org, payload['email'], payload['email'])\n\n    return user\n\n\ndef log_user_logged_in(app, user):\n    event = {\n        'org_id': user.org_id,\n        'user_id': user.id,\n        'action': 'login',\n        'object_type': 'redash',\n        'timestamp': int(time.time()),\n        'user_agent': request.user_agent.string,\n        'ip': request.remote_addr\n    }\n\n    record_event.delay(event)\n\n\n@login_manager.unauthorized_handler\ndef redirect_to_login():\n    if request.is_xhr or '/api/' in request.path:\n        response = jsonify({'message': \"Couldn't find resource. Please login and try again.\"})\n        response.status_code = 404\n        return response\n\n    login_url = get_login_url(next=request.url, external=False)\n\n    return redirect(login_url)\n\n\ndef logout_and_redirect_to_index():\n    logout_user()\n\n    if settings.MULTI_ORG and current_org == None:\n        index_url = '/'\n    elif settings.MULTI_ORG:\n        index_url = url_for('redash.index', org_slug=current_org.slug, _external=False)\n    else:\n        index_url = url_for('redash.index', _external=False)\n\n    return redirect(index_url)\n\n\ndef init_app(app):\n    from redash.authentication import google_oauth, saml_auth, remote_user_auth, ldap_auth\n\n    login_manager.init_app(app)\n    login_manager.anonymous_user = models.AnonymousUser\n\n    app.register_blueprint(google_oauth.blueprint)\n    app.register_blueprint(saml_auth.blueprint)\n    app.register_blueprint(remote_user_auth.blueprint)\n    app.register_blueprint(ldap_auth.blueprint)\n\n    user_logged_in.connect(log_user_logged_in)\n    login_manager.request_loader(request_loader)\n\n\ndef create_and_login_user(org, name, email, picture=None):\n    try:\n        user_object = models.User.get_by_email_and_org(email, org)\n        if user_object.is_disabled:\n            return None\n        if user_object.is_invitation_pending:\n            user_object.is_invitation_pending = False\n            models.db.session.commit()\n        if user_object.name != name:\n            logger.debug(\"Updating user name (%r -> %r)\", user_object.name, name)\n            user_object.name = name\n            models.db.session.commit()\n    except NoResultFound:\n        logger.debug(\"Creating user object (%r)\", name)\n        user_object = models.User(org=org, name=name, email=email, is_invitation_pending=False,\n                                  _profile_image_url=picture, group_ids=[org.default_group.id])\n        models.db.session.add(user_object)\n        models.db.session.commit()\n\n    login_user(user_object, remember=True)\n\n    return user_object\n\n\ndef get_next_path(unsafe_next_path):\n    if not unsafe_next_path:\n        return ''\n\n    # Preventing open redirection attacks\n    parts = list(urlsplit(unsafe_next_path))\n    parts[0] = ''  # clear scheme\n    parts[1] = ''  # clear netloc\n    safe_next_path = urlunsplit(parts)\n\n    return safe_next_path\n", "path": "redash/authentication/__init__.py"}], "after_files": [{"content": "import hashlib\nimport hmac\nimport logging\nimport time\nfrom urlparse import urlsplit, urlunsplit\n\nfrom flask import jsonify, redirect, request, url_for\nfrom flask_login import LoginManager, login_user, logout_user, user_logged_in\nfrom redash import models, settings\nfrom redash.authentication import jwt_auth\nfrom redash.authentication.org_resolving import current_org\nfrom redash.settings.organization import settings as org_settings\nfrom redash.tasks import record_event\nfrom sqlalchemy.orm.exc import NoResultFound\nfrom werkzeug.exceptions import Unauthorized\n\nlogin_manager = LoginManager()\nlogger = logging.getLogger('authentication')\n\n\ndef get_login_url(external=False, next=\"/\"):\n    if settings.MULTI_ORG and current_org == None:\n        login_url = '/'\n    elif settings.MULTI_ORG:\n        login_url = url_for('redash.login', org_slug=current_org.slug, next=next, _external=external)\n    else:\n        login_url = url_for('redash.login', next=next, _external=external)\n\n    return login_url\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_with_identity):\n    user = api_key_load_user_from_request(request)\n    if user:\n        return user\n\n    org = current_org._get_current_object()\n\n    try:\n        user_id, _ = user_id_with_identity.split(\"-\")\n        user = models.User.get_by_id_and_org(user_id, org)\n        if user.is_disabled or user.get_id() != user_id_with_identity:\n            return None\n\n        return user\n    except (models.NoResultFound, ValueError, AttributeError):\n        return None\n\n\ndef request_loader(request):\n    user = None\n    if settings.AUTH_TYPE == 'hmac':\n        user = hmac_load_user_from_request(request)\n    elif settings.AUTH_TYPE == 'api_key':\n        user = api_key_load_user_from_request(request)\n    else:\n        logger.warning(\"Unknown authentication type ({}). Using default (HMAC).\".format(settings.AUTH_TYPE))\n        user = hmac_load_user_from_request(request)\n\n    if org_settings['auth_jwt_login_enabled'] and user is None:\n        user = jwt_token_load_user_from_request(request)\n    return user\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.query.get(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.query.filter(models.Query.id == query_id).one()\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, query.org, query.groups.keys(), name=\"ApiKey: Query {}\".format(query.id))\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\n    # TODO: once we switch all api key storage into the ApiKey model, this code will be much simplified\n    org = current_org._get_current_object()\n    try:\n        user = models.User.get_by_api_key_and_org(api_key, org)\n        if user.is_disabled:\n            user = None\n    except models.NoResultFound:\n        try:\n            api_key = models.ApiKey.get_by_api_key(api_key)\n            user = models.ApiUser(api_key, api_key.org, [])\n        except models.NoResultFound:\n            if query_id:\n                query = models.Query.get_by_id_and_org(query_id, org)\n                if query and query.api_key == api_key:\n                    user = models.ApiUser(api_key, query.org, query.groups.keys(), name=\"ApiKey: Query {}\".format(query.id))\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 not None:\n        return api_key\n\n    if request.headers.get('Authorization'):\n        auth_header = request.headers.get('Authorization')\n        api_key = auth_header.replace('Key ', '', 1)\n    elif request.view_args is not None and request.view_args.get('token'):\n        api_key = request.view_args['token']\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    if request.view_args is not None:\n        query_id = request.view_args.get('query_id', None)\n        user = get_user_from_api_key(api_key, query_id)\n    else:\n        user = None\n\n    return user\n\n\ndef jwt_token_load_user_from_request(request):\n    org = current_org._get_current_object()\n\n    payload = None\n\n    if org_settings['auth_jwt_auth_cookie_name']:\n        jwt_token = request.cookies.get(org_settings['auth_jwt_auth_cookie_name'], None)\n    elif org_settings['auth_jwt_auth_header_name']:\n        jwt_token = request.headers.get(org_settings['auth_jwt_auth_header_name'], None)\n    else:\n        return None\n\n    if jwt_token:\n        payload, token_is_valid = jwt_auth.verify_jwt_token(\n            jwt_token,\n            expected_issuer=org_settings['auth_jwt_auth_issuer'],\n            expected_audience=org_settings['auth_jwt_auth_audience'],\n            algorithms=org_settings['auth_jwt_auth_algorithms'],\n            public_certs_url=org_settings['auth_jwt_auth_public_certs_url'],\n        )\n        if not token_is_valid:\n            raise Unauthorized('Invalid JWT token')\n\n    if not payload:\n        return\n\n    try:\n        user = models.User.get_by_email_and_org(payload['email'], org)\n    except models.NoResultFound:\n        user = create_and_login_user(current_org, payload['email'], payload['email'])\n\n    return user\n\n\ndef log_user_logged_in(app, user):\n    event = {\n        'org_id': user.org_id,\n        'user_id': user.id,\n        'action': 'login',\n        'object_type': 'redash',\n        'timestamp': int(time.time()),\n        'user_agent': request.user_agent.string,\n        'ip': request.remote_addr\n    }\n\n    record_event.delay(event)\n\n\n@login_manager.unauthorized_handler\ndef redirect_to_login():\n    if request.is_xhr or '/api/' in request.path:\n        response = jsonify({'message': \"Couldn't find resource. Please login and try again.\"})\n        response.status_code = 404\n        return response\n\n    login_url = get_login_url(next=request.url, external=False)\n\n    return redirect(login_url)\n\n\ndef logout_and_redirect_to_index():\n    logout_user()\n\n    if settings.MULTI_ORG and current_org == None:\n        index_url = '/'\n    elif settings.MULTI_ORG:\n        index_url = url_for('redash.index', org_slug=current_org.slug, _external=False)\n    else:\n        index_url = url_for('redash.index', _external=False)\n\n    return redirect(index_url)\n\n\ndef init_app(app):\n    from redash.authentication import google_oauth, saml_auth, remote_user_auth, ldap_auth\n\n    login_manager.init_app(app)\n    login_manager.anonymous_user = models.AnonymousUser\n\n    app.register_blueprint(google_oauth.blueprint)\n    app.register_blueprint(saml_auth.blueprint)\n    app.register_blueprint(remote_user_auth.blueprint)\n    app.register_blueprint(ldap_auth.blueprint)\n\n    user_logged_in.connect(log_user_logged_in)\n    login_manager.request_loader(request_loader)\n\n\ndef create_and_login_user(org, name, email, picture=None):\n    try:\n        user_object = models.User.get_by_email_and_org(email, org)\n        if user_object.is_disabled:\n            return None\n        if user_object.is_invitation_pending:\n            user_object.is_invitation_pending = False\n            models.db.session.commit()\n        if user_object.name != name:\n            logger.debug(\"Updating user name (%r -> %r)\", user_object.name, name)\n            user_object.name = name\n            models.db.session.commit()\n    except NoResultFound:\n        logger.debug(\"Creating user object (%r)\", name)\n        user_object = models.User(org=org, name=name, email=email, is_invitation_pending=False,\n                                  _profile_image_url=picture, group_ids=[org.default_group.id])\n        models.db.session.add(user_object)\n        models.db.session.commit()\n\n    login_user(user_object, remember=True)\n\n    return user_object\n\n\ndef get_next_path(unsafe_next_path):\n    if not unsafe_next_path:\n        return ''\n\n    # Preventing open redirection attacks\n    parts = list(urlsplit(unsafe_next_path))\n    parts[0] = ''  # clear scheme\n    parts[1] = ''  # clear netloc\n    safe_next_path = urlunsplit(parts)\n\n    return safe_next_path\n", "path": "redash/authentication/__init__.py"}]}