We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Authentication is currently broken 
When attempting to log into the web app when running locally, we encounter this error:

```
Traceback (most recent call last):
  File "python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "d/jwql/jwql/website/apps/jwql/oauth.py", line 113, in authorize
    request, headers={'Accept': 'application/json'}
  File "python3.6/site-packages/authlib/integrations/django_client/remote_app.py", line 63, in authorize_access_token
    return self.fetch_access_token(**params)
  File "python3.6/site-packages/authlib/integrations/_client/remote_app.py", line 106, in fetch_access_token
    token = client.fetch_token(token_endpoint, **kwargs)
  File "python3.6/site-packages/authlib/oauth2/client.py", line 202, in fetch_token
    headers=headers, **session_kwargs
  File "python3.6/site-packages/authlib/oauth2/client.py", line 223, in _fetch_token
    return self.parse_response_token(resp.json())
  File "python3.6/site-packages/requests/models.py", line 898, in json
    return complexjson.loads(self.text, **kwargs)
  File "python3.6/json/__init__.py", line 354, in loads
    return _default_decoder.decode(s)
  File "python3.6/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "python3.6/json/decoder.py", line 357, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `jwql/website/apps/jwql/oauth.py`
Content:
```
1 """Provides an OAuth object for authentication of the ``jwql`` web app,
2 as well as decorator functions to require user authentication in other
3 views of the web application.
4 
5 
6 Authors
7 -------
8 
9     - Matthew Bourque
10     - Christian Mesh
11 
12 Use
13 ---
14 
15     This module is intended to be imported and used as such:
16     ::
17 
18         from .oauth import auth_info
19         from .oauth import auth_required
20         from .oauth import JWQL_OAUTH
21 
22         @auth_info
23         def some_view(request):
24             pass
25 
26         @auth_required
27         def login(request):
28             pass
29 
30 References
31 ----------
32     Much of this code was taken from the ``authlib`` documentation,
33     found here: ``http://docs.authlib.org/en/latest/client/django.html``
34 
35 Dependencies
36 ------------
37     The user must have a configuration file named ``config.json``
38     placed in the ``jwql/utils/`` directory.
39 """
40 
41 import os
42 import requests
43 
44 from authlib.django.client import OAuth
45 from django.shortcuts import redirect, render
46 
47 import jwql
48 from jwql.utils.constants import MONITORS
49 from jwql.utils.utils import get_base_url, get_config, check_config_for_key
50 
51 PREV_PAGE = '/'
52 
53 
54 def register_oauth():
55     """Register the ``jwql`` application with the ``auth.mast``
56     authentication service.
57 
58     Returns
59     -------
60     oauth : Object
61         An object containing methods to authenticate a user, provided
62         by the ``auth.mast`` service.
63     """
64 
65     # Get configuration parameters
66     for key in ['client_id', 'client_secret', 'auth_mast']:
67         check_config_for_key(key)
68     client_id = get_config()['client_id']
69     client_secret = get_config()['client_secret']
70     auth_mast = get_config()['auth_mast']
71 
72     # Register with auth.mast
73     oauth = OAuth()
74     client_kwargs = {'scope': 'mast:user:info'}
75     oauth.register(
76         'mast_auth',
77         client_id='{}'.format(client_id),
78         client_secret='{}'.format(client_secret),
79         access_token_url='https://{}/oauth/access_token?client_secret={}'.format(
80             auth_mast, client_secret
81         ),
82         access_token_params=None,
83         refresh_token_url=None,
84         authorize_url='https://{}/oauth/authorize'.format(auth_mast),
85         api_base_url='https://{}/1.1/'.format(auth_mast),
86         client_kwargs=client_kwargs)
87 
88     return oauth
89 
90 
91 JWQL_OAUTH = register_oauth()
92 
93 
94 def authorize(request):
95     """Spawn the authentication process for the user
96 
97     The authentication process involves retreiving an access token
98     from ``auth.mast`` and porting the data to a cookie.
99 
100     Parameters
101     ----------
102     request : HttpRequest object
103         Incoming request from the webpage
104 
105     Returns
106     -------
107     HttpResponse object
108         Outgoing response sent to the webpage
109     """
110 
111     # Get auth.mast token
112     token = JWQL_OAUTH.mast_auth.authorize_access_token(
113         request, headers={'Accept': 'application/json'}
114     )
115 
116     # Determine domain
117     base_url = get_base_url()
118     if '127' in base_url:
119         domain = '127.0.0.1'
120     else:
121         domain = base_url.split('//')[-1]
122 
123     # Set secure cookie parameters
124     cookie_args = {}
125     # cookie_args['domain'] = domain  # Currently broken
126     # cookie_args['secure'] = True  # Currently broken
127     cookie_args['httponly'] = True
128 
129     # Set the cookie
130     response = redirect(PREV_PAGE)
131     response.set_cookie("ASB-AUTH", token["access_token"], **cookie_args)
132 
133     return response
134 
135 
136 def auth_info(fn):
137     """A decorator function that will return user credentials along
138     with what is returned by the original function.
139 
140     Parameters
141     ----------
142     fn : function
143         The function to decorate
144 
145     Returns
146     -------
147     user_info : function
148         The decorated function
149     """
150 
151     def user_info(request, **kwargs):
152         """Store authenticated user credentials in a cookie and return
153         it.  If the user is not authenticated, store no credentials in
154         the cookie.
155 
156         Parameters
157         ----------
158         request : HttpRequest object
159             Incoming request from the webpage
160 
161         Returns
162         -------
163         fn : function
164             The decorated function
165         """
166 
167         cookie = request.COOKIES.get("ASB-AUTH")
168 
169         # If user is authenticated, return user credentials
170         if cookie is not None:
171             check_config_for_key('auth_mast')
172             # Note: for now, this must be the development version
173             auth_mast = get_config()['auth_mast']
174 
175             response = requests.get(
176                 'https://{}/info'.format(auth_mast),
177                 headers={'Accept': 'application/json',
178                          'Authorization': 'token {}'.format(cookie)})
179             response = response.json()
180             response['access_token'] = cookie
181 
182         # If user is not authenticated, return no credentials
183         else:
184             response = {'ezid': None, "anon": True, 'access_token': None}
185 
186         return fn(request, response, **kwargs)
187 
188     return user_info
189 
190 
191 def auth_required(fn):
192     """A decorator function that requires the given function to have
193     authentication through ``auth.mast`` set up.
194 
195     Parameters
196     ----------
197     fn : function
198         The function to decorate
199 
200     Returns
201     -------
202     check_auth : function
203         The decorated function
204     """
205 
206     @auth_info
207     def check_auth(request, user, **kwargs):
208         """Check if the user is authenticated through ``auth.mast``.
209         If not, perform the authorization.
210 
211         Parameters
212         ----------
213         request : HttpRequest object
214             Incoming request from the webpage
215         user : dict
216             A dictionary of user credentials
217 
218         Returns
219         -------
220         fn : function
221             The decorated function
222         """
223 
224         # If user is currently anonymous, require a login
225         if user['ezid']:
226 
227             return fn(request, user, **kwargs)
228 
229         else:
230             template = 'not_authenticated.html'
231             context = {'inst': ''}
232 
233             return render(request, template, context)
234 
235     return check_auth
236 
237 
238 @auth_info
239 def login(request, user):
240     """Spawn a login process for the user
241 
242     The ``auth_requred`` decorator is used to require that the user
243     authenticate through ``auth.mast``, then the user is redirected
244     back to the homepage.
245 
246     Parameters
247     ----------
248     request : HttpRequest object
249         Incoming request from the webpage
250     user : dict
251         A dictionary of user credentials.
252 
253     Returns
254     -------
255     HttpResponse object
256         Outgoing response sent to the webpage
257     """
258 
259     # Redirect to oauth login
260     global PREV_PAGE
261     PREV_PAGE = request.META.get('HTTP_REFERER')
262     redirect_uri = os.path.join(get_base_url(), 'authorize')
263 
264     return JWQL_OAUTH.mast_auth.authorize_redirect(request, redirect_uri)
265 
266 
267 def logout(request):
268     """Spawn a logout process for the user
269 
270     Upon logout, the user's ``auth.mast`` credientials are removed and
271     the user is redirected back to the homepage.
272 
273     Parameters
274     ----------
275     request : HttpRequest object
276         Incoming request from the webpage
277     user : dict
278         A dictionary of user credentials.
279 
280     Returns
281     -------
282     HttpResponse object
283         Outgoing response sent to the webpage
284     """
285 
286     global PREV_PAGE
287     PREV_PAGE = request.META.get('HTTP_REFERER')
288     response = redirect(PREV_PAGE)
289     response.delete_cookie("ASB-AUTH")
290 
291     return response
292
```

Path: `setup.py`
Content:
```
1 import numpy as np
2 from setuptools import setup
3 from setuptools import find_packages
4 
5 VERSION = '0.23.0'
6 
7 AUTHORS = 'Matthew Bourque, Lauren Chambers, Misty Cracraft, Mike Engesser, Mees Fix, Joe Filippazzo, Bryan Hilbert, '
8 AUTHORS += 'Graham Kanarek, Teagan King, Catherine Martlin, Maria Pena-Guerrero, Johannes Sahlmann, Ben Sunnquist'
9 
10 DESCRIPTION = 'The James Webb Space Telescope Quicklook Project'
11 
12 DEPENDENCY_LINKS = ['git+https://github.com/spacetelescope/jwst@0.16.2',
13                     'git+https://github.com/spacetelescope/jwst_reffiles#egg=jwst_reffiles'
14                     ]
15 REQUIRES = [
16     'asdf>=2.3.3',
17     'astropy>=3.2.1',
18     'astroquery>=0.3.9',
19     'authlib',
20     'bokeh>=1.0,<1.4',
21     'codecov',
22     'crds',
23     'django>=2.0,<3.0',
24     'flake8',
25     'inflection',
26     'ipython',
27     'jinja2',
28     'jsonschema',
29     'jwedb>=0.0.3',
30     'matplotlib',
31     'nodejs',
32     'numpy',
33     'numpydoc',
34     'pandas',
35     'psycopg2',
36     'pysiaf',
37     'pytest',
38     'pytest-cov',
39     'scipy',
40     'sphinx',
41     'sqlalchemy',
42     'stsci_rtd_theme',
43     'twine'
44 ]
45 
46 setup(
47     name='jwql',
48     version=VERSION,
49     description=DESCRIPTION,
50     url='https://github.com/spacetelescope/jwql.git',
51     author=AUTHORS,
52     author_email='jwql@stsci.edu',
53     license='BSD',
54     keywords=['astronomy', 'python'],
55     classifiers=['Programming Language :: Python'],
56     packages=find_packages(),
57     install_requires=REQUIRES,
58     dependency_links=DEPENDENCY_LINKS,
59     include_package_data=True,
60     include_dirs=[np.get_include()],
61 )
62
```
--- 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/jwql/website/apps/jwql/oauth.py b/jwql/website/apps/jwql/oauth.py
--- a/jwql/website/apps/jwql/oauth.py
+++ b/jwql/website/apps/jwql/oauth.py
@@ -8,6 +8,7 @@
 
     - Matthew Bourque
     - Christian Mesh
+    - Ben Falk
 
 Use
 ---
@@ -41,8 +42,9 @@
 import os
 import requests
 
-from authlib.django.client import OAuth
+from authlib.integrations.django_client import OAuth
 from django.shortcuts import redirect, render
+from django.urls import reverse
 
 import jwql
 from jwql.utils.constants import MONITORS
@@ -71,14 +73,15 @@
 
     # Register with auth.mast
     oauth = OAuth()
-    client_kwargs = {'scope': 'mast:user:info'}
+    client_kwargs = {
+        'scope': 'mast:user:info',
+        'token_endpoint_auth_method': 'client_secret_basic',
+        'token_placement': 'header'}
     oauth.register(
         'mast_auth',
         client_id='{}'.format(client_id),
         client_secret='{}'.format(client_secret),
-        access_token_url='https://{}/oauth/access_token?client_secret={}'.format(
-            auth_mast, client_secret
-        ),
+        access_token_url='https://{}/oauth/token'.format(auth_mast),
         access_token_params=None,
         refresh_token_url=None,
         authorize_url='https://{}/oauth/authorize'.format(auth_mast),
@@ -109,9 +112,7 @@
     """
 
     # Get auth.mast token
-    token = JWQL_OAUTH.mast_auth.authorize_access_token(
-        request, headers={'Accept': 'application/json'}
-    )
+    token = JWQL_OAUTH.mast_auth.authorize_access_token(request)
 
     # Determine domain
     base_url = get_base_url()
@@ -259,7 +260,7 @@
     # Redirect to oauth login
     global PREV_PAGE
     PREV_PAGE = request.META.get('HTTP_REFERER')
-    redirect_uri = os.path.join(get_base_url(), 'authorize')
+    redirect_uri = f"{get_base_url()}{reverse('jwql:authorize')}"
 
     return JWQL_OAUTH.mast_auth.authorize_redirect(request, redirect_uri)
 
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -20,6 +20,7 @@
     'bokeh>=1.0,<1.4',
     'codecov',
     'crds',
+    'cryptography',
     'django>=2.0,<3.0',
     'flake8',
     'inflection',

{"golden_diff": "diff --git a/jwql/website/apps/jwql/oauth.py b/jwql/website/apps/jwql/oauth.py\n--- a/jwql/website/apps/jwql/oauth.py\n+++ b/jwql/website/apps/jwql/oauth.py\n@@ -8,6 +8,7 @@\n \n     - Matthew Bourque\n     - Christian Mesh\n+    - Ben Falk\n \n Use\n ---\n@@ -41,8 +42,9 @@\n import os\n import requests\n \n-from authlib.django.client import OAuth\n+from authlib.integrations.django_client import OAuth\n from django.shortcuts import redirect, render\n+from django.urls import reverse\n \n import jwql\n from jwql.utils.constants import MONITORS\n@@ -71,14 +73,15 @@\n \n     # Register with auth.mast\n     oauth = OAuth()\n-    client_kwargs = {'scope': 'mast:user:info'}\n+    client_kwargs = {\n+        'scope': 'mast:user:info',\n+        'token_endpoint_auth_method': 'client_secret_basic',\n+        'token_placement': 'header'}\n     oauth.register(\n         'mast_auth',\n         client_id='{}'.format(client_id),\n         client_secret='{}'.format(client_secret),\n-        access_token_url='https://{}/oauth/access_token?client_secret={}'.format(\n-            auth_mast, client_secret\n-        ),\n+        access_token_url='https://{}/oauth/token'.format(auth_mast),\n         access_token_params=None,\n         refresh_token_url=None,\n         authorize_url='https://{}/oauth/authorize'.format(auth_mast),\n@@ -109,9 +112,7 @@\n     \"\"\"\n \n     # Get auth.mast token\n-    token = JWQL_OAUTH.mast_auth.authorize_access_token(\n-        request, headers={'Accept': 'application/json'}\n-    )\n+    token = JWQL_OAUTH.mast_auth.authorize_access_token(request)\n \n     # Determine domain\n     base_url = get_base_url()\n@@ -259,7 +260,7 @@\n     # Redirect to oauth login\n     global PREV_PAGE\n     PREV_PAGE = request.META.get('HTTP_REFERER')\n-    redirect_uri = os.path.join(get_base_url(), 'authorize')\n+    redirect_uri = f\"{get_base_url()}{reverse('jwql:authorize')}\"\n \n     return JWQL_OAUTH.mast_auth.authorize_redirect(request, redirect_uri)\n \ndiff --git a/setup.py b/setup.py\n--- a/setup.py\n+++ b/setup.py\n@@ -20,6 +20,7 @@\n     'bokeh>=1.0,<1.4',\n     'codecov',\n     'crds',\n+    'cryptography',\n     'django>=2.0,<3.0',\n     'flake8',\n     'inflection',\n", "issue": "Authentication is currently broken \nWhen attempting to log into the web app when running locally, we encounter this error:\r\n\r\n```\r\nTraceback (most recent call last):\r\n  File \"python3.6/site-packages/django/core/handlers/exception.py\", line 34, in inner\r\n    response = get_response(request)\r\n  File \"python3.6/site-packages/django/core/handlers/base.py\", line 115, in _get_response\r\n    response = self.process_exception_by_middleware(e, request)\r\n  File \"python3.6/site-packages/django/core/handlers/base.py\", line 113, in _get_response\r\n    response = wrapped_callback(request, *callback_args, **callback_kwargs)\r\n  File \"d/jwql/jwql/website/apps/jwql/oauth.py\", line 113, in authorize\r\n    request, headers={'Accept': 'application/json'}\r\n  File \"python3.6/site-packages/authlib/integrations/django_client/remote_app.py\", line 63, in authorize_access_token\r\n    return self.fetch_access_token(**params)\r\n  File \"python3.6/site-packages/authlib/integrations/_client/remote_app.py\", line 106, in fetch_access_token\r\n    token = client.fetch_token(token_endpoint, **kwargs)\r\n  File \"python3.6/site-packages/authlib/oauth2/client.py\", line 202, in fetch_token\r\n    headers=headers, **session_kwargs\r\n  File \"python3.6/site-packages/authlib/oauth2/client.py\", line 223, in _fetch_token\r\n    return self.parse_response_token(resp.json())\r\n  File \"python3.6/site-packages/requests/models.py\", line 898, in json\r\n    return complexjson.loads(self.text, **kwargs)\r\n  File \"python3.6/json/__init__.py\", line 354, in loads\r\n    return _default_decoder.decode(s)\r\n  File \"python3.6/json/decoder.py\", line 339, in decode\r\n    obj, end = self.raw_decode(s, idx=_w(s, 0).end())\r\n  File \"python3.6/json/decoder.py\", line 357, in raw_decode\r\n    raise JSONDecodeError(\"Expecting value\", s, err.value) from None\r\njson.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)\r\n```\n", "before_files": [{"content": "\"\"\"Provides an OAuth object for authentication of the ``jwql`` web app,\nas well as decorator functions to require user authentication in other\nviews of the web application.\n\n\nAuthors\n-------\n\n    - Matthew Bourque\n    - Christian Mesh\n\nUse\n---\n\n    This module is intended to be imported and used as such:\n    ::\n\n        from .oauth import auth_info\n        from .oauth import auth_required\n        from .oauth import JWQL_OAUTH\n\n        @auth_info\n        def some_view(request):\n            pass\n\n        @auth_required\n        def login(request):\n            pass\n\nReferences\n----------\n    Much of this code was taken from the ``authlib`` documentation,\n    found here: ``http://docs.authlib.org/en/latest/client/django.html``\n\nDependencies\n------------\n    The user must have a configuration file named ``config.json``\n    placed in the ``jwql/utils/`` directory.\n\"\"\"\n\nimport os\nimport requests\n\nfrom authlib.django.client import OAuth\nfrom django.shortcuts import redirect, render\n\nimport jwql\nfrom jwql.utils.constants import MONITORS\nfrom jwql.utils.utils import get_base_url, get_config, check_config_for_key\n\nPREV_PAGE = '/'\n\n\ndef register_oauth():\n    \"\"\"Register the ``jwql`` application with the ``auth.mast``\n    authentication service.\n\n    Returns\n    -------\n    oauth : Object\n        An object containing methods to authenticate a user, provided\n        by the ``auth.mast`` service.\n    \"\"\"\n\n    # Get configuration parameters\n    for key in ['client_id', 'client_secret', 'auth_mast']:\n        check_config_for_key(key)\n    client_id = get_config()['client_id']\n    client_secret = get_config()['client_secret']\n    auth_mast = get_config()['auth_mast']\n\n    # Register with auth.mast\n    oauth = OAuth()\n    client_kwargs = {'scope': 'mast:user:info'}\n    oauth.register(\n        'mast_auth',\n        client_id='{}'.format(client_id),\n        client_secret='{}'.format(client_secret),\n        access_token_url='https://{}/oauth/access_token?client_secret={}'.format(\n            auth_mast, client_secret\n        ),\n        access_token_params=None,\n        refresh_token_url=None,\n        authorize_url='https://{}/oauth/authorize'.format(auth_mast),\n        api_base_url='https://{}/1.1/'.format(auth_mast),\n        client_kwargs=client_kwargs)\n\n    return oauth\n\n\nJWQL_OAUTH = register_oauth()\n\n\ndef authorize(request):\n    \"\"\"Spawn the authentication process for the user\n\n    The authentication process involves retreiving an access token\n    from ``auth.mast`` and porting the data to a cookie.\n\n    Parameters\n    ----------\n    request : HttpRequest object\n        Incoming request from the webpage\n\n    Returns\n    -------\n    HttpResponse object\n        Outgoing response sent to the webpage\n    \"\"\"\n\n    # Get auth.mast token\n    token = JWQL_OAUTH.mast_auth.authorize_access_token(\n        request, headers={'Accept': 'application/json'}\n    )\n\n    # Determine domain\n    base_url = get_base_url()\n    if '127' in base_url:\n        domain = '127.0.0.1'\n    else:\n        domain = base_url.split('//')[-1]\n\n    # Set secure cookie parameters\n    cookie_args = {}\n    # cookie_args['domain'] = domain  # Currently broken\n    # cookie_args['secure'] = True  # Currently broken\n    cookie_args['httponly'] = True\n\n    # Set the cookie\n    response = redirect(PREV_PAGE)\n    response.set_cookie(\"ASB-AUTH\", token[\"access_token\"], **cookie_args)\n\n    return response\n\n\ndef auth_info(fn):\n    \"\"\"A decorator function that will return user credentials along\n    with what is returned by the original function.\n\n    Parameters\n    ----------\n    fn : function\n        The function to decorate\n\n    Returns\n    -------\n    user_info : function\n        The decorated function\n    \"\"\"\n\n    def user_info(request, **kwargs):\n        \"\"\"Store authenticated user credentials in a cookie and return\n        it.  If the user is not authenticated, store no credentials in\n        the cookie.\n\n        Parameters\n        ----------\n        request : HttpRequest object\n            Incoming request from the webpage\n\n        Returns\n        -------\n        fn : function\n            The decorated function\n        \"\"\"\n\n        cookie = request.COOKIES.get(\"ASB-AUTH\")\n\n        # If user is authenticated, return user credentials\n        if cookie is not None:\n            check_config_for_key('auth_mast')\n            # Note: for now, this must be the development version\n            auth_mast = get_config()['auth_mast']\n\n            response = requests.get(\n                'https://{}/info'.format(auth_mast),\n                headers={'Accept': 'application/json',\n                         'Authorization': 'token {}'.format(cookie)})\n            response = response.json()\n            response['access_token'] = cookie\n\n        # If user is not authenticated, return no credentials\n        else:\n            response = {'ezid': None, \"anon\": True, 'access_token': None}\n\n        return fn(request, response, **kwargs)\n\n    return user_info\n\n\ndef auth_required(fn):\n    \"\"\"A decorator function that requires the given function to have\n    authentication through ``auth.mast`` set up.\n\n    Parameters\n    ----------\n    fn : function\n        The function to decorate\n\n    Returns\n    -------\n    check_auth : function\n        The decorated function\n    \"\"\"\n\n    @auth_info\n    def check_auth(request, user, **kwargs):\n        \"\"\"Check if the user is authenticated through ``auth.mast``.\n        If not, perform the authorization.\n\n        Parameters\n        ----------\n        request : HttpRequest object\n            Incoming request from the webpage\n        user : dict\n            A dictionary of user credentials\n\n        Returns\n        -------\n        fn : function\n            The decorated function\n        \"\"\"\n\n        # If user is currently anonymous, require a login\n        if user['ezid']:\n\n            return fn(request, user, **kwargs)\n\n        else:\n            template = 'not_authenticated.html'\n            context = {'inst': ''}\n\n            return render(request, template, context)\n\n    return check_auth\n\n\n@auth_info\ndef login(request, user):\n    \"\"\"Spawn a login process for the user\n\n    The ``auth_requred`` decorator is used to require that the user\n    authenticate through ``auth.mast``, then the user is redirected\n    back to the homepage.\n\n    Parameters\n    ----------\n    request : HttpRequest object\n        Incoming request from the webpage\n    user : dict\n        A dictionary of user credentials.\n\n    Returns\n    -------\n    HttpResponse object\n        Outgoing response sent to the webpage\n    \"\"\"\n\n    # Redirect to oauth login\n    global PREV_PAGE\n    PREV_PAGE = request.META.get('HTTP_REFERER')\n    redirect_uri = os.path.join(get_base_url(), 'authorize')\n\n    return JWQL_OAUTH.mast_auth.authorize_redirect(request, redirect_uri)\n\n\ndef logout(request):\n    \"\"\"Spawn a logout process for the user\n\n    Upon logout, the user's ``auth.mast`` credientials are removed and\n    the user is redirected back to the homepage.\n\n    Parameters\n    ----------\n    request : HttpRequest object\n        Incoming request from the webpage\n    user : dict\n        A dictionary of user credentials.\n\n    Returns\n    -------\n    HttpResponse object\n        Outgoing response sent to the webpage\n    \"\"\"\n\n    global PREV_PAGE\n    PREV_PAGE = request.META.get('HTTP_REFERER')\n    response = redirect(PREV_PAGE)\n    response.delete_cookie(\"ASB-AUTH\")\n\n    return response\n", "path": "jwql/website/apps/jwql/oauth.py"}, {"content": "import numpy as np\nfrom setuptools import setup\nfrom setuptools import find_packages\n\nVERSION = '0.23.0'\n\nAUTHORS = 'Matthew Bourque, Lauren Chambers, Misty Cracraft, Mike Engesser, Mees Fix, Joe Filippazzo, Bryan Hilbert, '\nAUTHORS += 'Graham Kanarek, Teagan King, Catherine Martlin, Maria Pena-Guerrero, Johannes Sahlmann, Ben Sunnquist'\n\nDESCRIPTION = 'The James Webb Space Telescope Quicklook Project'\n\nDEPENDENCY_LINKS = ['git+https://github.com/spacetelescope/jwst@0.16.2',\n                    'git+https://github.com/spacetelescope/jwst_reffiles#egg=jwst_reffiles'\n                    ]\nREQUIRES = [\n    'asdf>=2.3.3',\n    'astropy>=3.2.1',\n    'astroquery>=0.3.9',\n    'authlib',\n    'bokeh>=1.0,<1.4',\n    'codecov',\n    'crds',\n    'django>=2.0,<3.0',\n    'flake8',\n    'inflection',\n    'ipython',\n    'jinja2',\n    'jsonschema',\n    'jwedb>=0.0.3',\n    'matplotlib',\n    'nodejs',\n    'numpy',\n    'numpydoc',\n    'pandas',\n    'psycopg2',\n    'pysiaf',\n    'pytest',\n    'pytest-cov',\n    'scipy',\n    'sphinx',\n    'sqlalchemy',\n    'stsci_rtd_theme',\n    'twine'\n]\n\nsetup(\n    name='jwql',\n    version=VERSION,\n    description=DESCRIPTION,\n    url='https://github.com/spacetelescope/jwql.git',\n    author=AUTHORS,\n    author_email='jwql@stsci.edu',\n    license='BSD',\n    keywords=['astronomy', 'python'],\n    classifiers=['Programming Language :: Python'],\n    packages=find_packages(),\n    install_requires=REQUIRES,\n    dependency_links=DEPENDENCY_LINKS,\n    include_package_data=True,\n    include_dirs=[np.get_include()],\n)\n", "path": "setup.py"}], "after_files": [{"content": "\"\"\"Provides an OAuth object for authentication of the ``jwql`` web app,\nas well as decorator functions to require user authentication in other\nviews of the web application.\n\n\nAuthors\n-------\n\n    - Matthew Bourque\n    - Christian Mesh\n    - Ben Falk\n\nUse\n---\n\n    This module is intended to be imported and used as such:\n    ::\n\n        from .oauth import auth_info\n        from .oauth import auth_required\n        from .oauth import JWQL_OAUTH\n\n        @auth_info\n        def some_view(request):\n            pass\n\n        @auth_required\n        def login(request):\n            pass\n\nReferences\n----------\n    Much of this code was taken from the ``authlib`` documentation,\n    found here: ``http://docs.authlib.org/en/latest/client/django.html``\n\nDependencies\n------------\n    The user must have a configuration file named ``config.json``\n    placed in the ``jwql/utils/`` directory.\n\"\"\"\n\nimport os\nimport requests\n\nfrom authlib.integrations.django_client import OAuth\nfrom django.shortcuts import redirect, render\nfrom django.urls import reverse\n\nimport jwql\nfrom jwql.utils.constants import MONITORS\nfrom jwql.utils.utils import get_base_url, get_config, check_config_for_key\n\nPREV_PAGE = '/'\n\n\ndef register_oauth():\n    \"\"\"Register the ``jwql`` application with the ``auth.mast``\n    authentication service.\n\n    Returns\n    -------\n    oauth : Object\n        An object containing methods to authenticate a user, provided\n        by the ``auth.mast`` service.\n    \"\"\"\n\n    # Get configuration parameters\n    for key in ['client_id', 'client_secret', 'auth_mast']:\n        check_config_for_key(key)\n    client_id = get_config()['client_id']\n    client_secret = get_config()['client_secret']\n    auth_mast = get_config()['auth_mast']\n\n    # Register with auth.mast\n    oauth = OAuth()\n    client_kwargs = {\n        'scope': 'mast:user:info',\n        'token_endpoint_auth_method': 'client_secret_basic',\n        'token_placement': 'header'}\n    oauth.register(\n        'mast_auth',\n        client_id='{}'.format(client_id),\n        client_secret='{}'.format(client_secret),\n        access_token_url='https://{}/oauth/token'.format(auth_mast),\n        access_token_params=None,\n        refresh_token_url=None,\n        authorize_url='https://{}/oauth/authorize'.format(auth_mast),\n        api_base_url='https://{}/1.1/'.format(auth_mast),\n        client_kwargs=client_kwargs)\n\n    return oauth\n\n\nJWQL_OAUTH = register_oauth()\n\n\ndef authorize(request):\n    \"\"\"Spawn the authentication process for the user\n\n    The authentication process involves retreiving an access token\n    from ``auth.mast`` and porting the data to a cookie.\n\n    Parameters\n    ----------\n    request : HttpRequest object\n        Incoming request from the webpage\n\n    Returns\n    -------\n    HttpResponse object\n        Outgoing response sent to the webpage\n    \"\"\"\n\n    # Get auth.mast token\n    token = JWQL_OAUTH.mast_auth.authorize_access_token(request)\n\n    # Determine domain\n    base_url = get_base_url()\n    if '127' in base_url:\n        domain = '127.0.0.1'\n    else:\n        domain = base_url.split('//')[-1]\n\n    # Set secure cookie parameters\n    cookie_args = {}\n    # cookie_args['domain'] = domain  # Currently broken\n    # cookie_args['secure'] = True  # Currently broken\n    cookie_args['httponly'] = True\n\n    # Set the cookie\n    response = redirect(PREV_PAGE)\n    response.set_cookie(\"ASB-AUTH\", token[\"access_token\"], **cookie_args)\n\n    return response\n\n\ndef auth_info(fn):\n    \"\"\"A decorator function that will return user credentials along\n    with what is returned by the original function.\n\n    Parameters\n    ----------\n    fn : function\n        The function to decorate\n\n    Returns\n    -------\n    user_info : function\n        The decorated function\n    \"\"\"\n\n    def user_info(request, **kwargs):\n        \"\"\"Store authenticated user credentials in a cookie and return\n        it.  If the user is not authenticated, store no credentials in\n        the cookie.\n\n        Parameters\n        ----------\n        request : HttpRequest object\n            Incoming request from the webpage\n\n        Returns\n        -------\n        fn : function\n            The decorated function\n        \"\"\"\n\n        cookie = request.COOKIES.get(\"ASB-AUTH\")\n\n        # If user is authenticated, return user credentials\n        if cookie is not None:\n            check_config_for_key('auth_mast')\n            # Note: for now, this must be the development version\n            auth_mast = get_config()['auth_mast']\n\n            response = requests.get(\n                'https://{}/info'.format(auth_mast),\n                headers={'Accept': 'application/json',\n                         'Authorization': 'token {}'.format(cookie)})\n            response = response.json()\n            response['access_token'] = cookie\n\n        # If user is not authenticated, return no credentials\n        else:\n            response = {'ezid': None, \"anon\": True, 'access_token': None}\n\n        return fn(request, response, **kwargs)\n\n    return user_info\n\n\ndef auth_required(fn):\n    \"\"\"A decorator function that requires the given function to have\n    authentication through ``auth.mast`` set up.\n\n    Parameters\n    ----------\n    fn : function\n        The function to decorate\n\n    Returns\n    -------\n    check_auth : function\n        The decorated function\n    \"\"\"\n\n    @auth_info\n    def check_auth(request, user, **kwargs):\n        \"\"\"Check if the user is authenticated through ``auth.mast``.\n        If not, perform the authorization.\n\n        Parameters\n        ----------\n        request : HttpRequest object\n            Incoming request from the webpage\n        user : dict\n            A dictionary of user credentials\n\n        Returns\n        -------\n        fn : function\n            The decorated function\n        \"\"\"\n\n        # If user is currently anonymous, require a login\n        if user['ezid']:\n\n            return fn(request, user, **kwargs)\n\n        else:\n            template = 'not_authenticated.html'\n            context = {'inst': ''}\n\n            return render(request, template, context)\n\n    return check_auth\n\n\n@auth_info\ndef login(request, user):\n    \"\"\"Spawn a login process for the user\n\n    The ``auth_requred`` decorator is used to require that the user\n    authenticate through ``auth.mast``, then the user is redirected\n    back to the homepage.\n\n    Parameters\n    ----------\n    request : HttpRequest object\n        Incoming request from the webpage\n    user : dict\n        A dictionary of user credentials.\n\n    Returns\n    -------\n    HttpResponse object\n        Outgoing response sent to the webpage\n    \"\"\"\n\n    # Redirect to oauth login\n    global PREV_PAGE\n    PREV_PAGE = request.META.get('HTTP_REFERER')\n    redirect_uri = f\"{get_base_url()}{reverse('jwql:authorize')}\"\n\n    return JWQL_OAUTH.mast_auth.authorize_redirect(request, redirect_uri)\n\n\ndef logout(request):\n    \"\"\"Spawn a logout process for the user\n\n    Upon logout, the user's ``auth.mast`` credientials are removed and\n    the user is redirected back to the homepage.\n\n    Parameters\n    ----------\n    request : HttpRequest object\n        Incoming request from the webpage\n    user : dict\n        A dictionary of user credentials.\n\n    Returns\n    -------\n    HttpResponse object\n        Outgoing response sent to the webpage\n    \"\"\"\n\n    global PREV_PAGE\n    PREV_PAGE = request.META.get('HTTP_REFERER')\n    response = redirect(PREV_PAGE)\n    response.delete_cookie(\"ASB-AUTH\")\n\n    return response\n", "path": "jwql/website/apps/jwql/oauth.py"}, {"content": "import numpy as np\nfrom setuptools import setup\nfrom setuptools import find_packages\n\nVERSION = '0.23.0'\n\nAUTHORS = 'Matthew Bourque, Lauren Chambers, Misty Cracraft, Mike Engesser, Mees Fix, Joe Filippazzo, Bryan Hilbert, '\nAUTHORS += 'Graham Kanarek, Teagan King, Catherine Martlin, Maria Pena-Guerrero, Johannes Sahlmann, Ben Sunnquist'\n\nDESCRIPTION = 'The James Webb Space Telescope Quicklook Project'\n\nDEPENDENCY_LINKS = ['git+https://github.com/spacetelescope/jwst@0.16.2',\n                    'git+https://github.com/spacetelescope/jwst_reffiles#egg=jwst_reffiles'\n                    ]\nREQUIRES = [\n    'asdf>=2.3.3',\n    'astropy>=3.2.1',\n    'astroquery>=0.3.9',\n    'authlib',\n    'bokeh>=1.0,<1.4',\n    'codecov',\n    'crds',\n    'cryptography',\n    'django>=2.0,<3.0',\n    'flake8',\n    'inflection',\n    'ipython',\n    'jinja2',\n    'jsonschema',\n    'jwedb>=0.0.3',\n    'matplotlib',\n    'nodejs',\n    'numpy',\n    'numpydoc',\n    'pandas',\n    'psycopg2',\n    'pysiaf',\n    'pytest',\n    'pytest-cov',\n    'scipy',\n    'sphinx',\n    'sqlalchemy',\n    'stsci_rtd_theme',\n    'twine'\n]\n\nsetup(\n    name='jwql',\n    version=VERSION,\n    description=DESCRIPTION,\n    url='https://github.com/spacetelescope/jwql.git',\n    author=AUTHORS,\n    author_email='jwql@stsci.edu',\n    license='BSD',\n    keywords=['astronomy', 'python'],\n    classifiers=['Programming Language :: Python'],\n    packages=find_packages(),\n    install_requires=REQUIRES,\n    dependency_links=DEPENDENCY_LINKS,\n    include_package_data=True,\n    include_dirs=[np.get_include()],\n)\n", "path": "setup.py"}]}