def test_auth_cookie_caches_calls_to_plotly(self): app = dash.Dash() app.scripts.config.serve_locally = True auth = PlotlyAuth(app, 'private-cookie-test', 'private', 'http://localhost:5000') app.layout = html.Div() creator = users['creator']['oauth_token'] with mock.patch('dash_auth.plotly_auth.check_view_access', wraps=plotly_auth.check_view_access) as wrapped: self.check_endpoints(auth, app, creator) res = self.check_endpoints(auth, app, creator) n_endpoints = (len(endpoints['protected']['get']) + len(endpoints['unprotected']['get'])) self.assertEqual(wrapped.call_count, n_endpoints * 2) access_granted_cookie = get_cookie(res, PlotlyAuth.AUTH_COOKIE_NAME) self.check_endpoints(auth, app, creator, ({ 'name': PlotlyAuth.AUTH_COOKIE_NAME, 'value': access_granted_cookie }, )) self.assertEqual(wrapped.call_count, n_endpoints * 2) # Regenerate tokens with a shorter expiration # User's won't actually do this in practice, we're # just doing it to shorten up the expiration from 5 min # to 10 seconds auth.config['permissions_cache_expiry'] = 10 auth.create_access_codes() res = self.check_endpoints(auth, app, creator) self.assertEqual(wrapped.call_count, n_endpoints * 3) # Using the same auth cookie should prevent an # additional access call access_granted_cookie = get_cookie(res, PlotlyAuth.AUTH_COOKIE_NAME) self.check_endpoints(auth, app, creator, ({ 'name': PlotlyAuth.AUTH_COOKIE_NAME, 'value': access_granted_cookie }, )) self.assertEqual(wrapped.call_count, (n_endpoints * 3)) # But after the expiration time (10 seconds), another call to # plotly should be made time.sleep(10) self.check_endpoints(auth, app, creator) self.assertEqual(wrapped.call_count, (n_endpoints * 4))
def create_apps(): app_permissions = ['public', 'private'] apps = {k: dash.Dash(k) for k in app_permissions} for app in list(apps.values()): app.scripts.config.serve_locally = True auths = { k: PlotlyAuth(apps[k], '{}-app-test'.format(k), k, 'http://localhost:5000') for k in app_permissions } apps['unregistered'] = dash.Dash('unregistered') apps['unregistered'].scripts.config.serve_locally = True return apps, auths
def login_success(self): app = dash.Dash() app.config.scripts.serve_locally = True auth = PlotlyAuth(app, 'test-auth-login-flow', 'private', 'https://dash-auth-app.herokuapp.com') app.layout = html.Div() client = app.server.test_client() csrf_token = get_cookie(client.get('/'), '_csrf_token') client.set_cookie('/', '_csrf_token', csrf_token) oauth_token = users['creator']['oauth_token'] res = client.post('_login', headers={ 'Authorization': 'Bearer {}'.format(oauth_token), 'X-CSRFToken': csrf_token }) self.assertEqual(res.status_code, 200) self.assertEqual(get_cookie(res, 'plotly_oauth_token'), oauth_token)
def test_permissions_can_change(self): app_name = 'private-flip-flop-app-test' app_url = 'http://localhost:5000' app = dash.Dash() app.scripts.config.serve_locally = True auth = PlotlyAuth(app, app_name, 'private', app_url) app.layout = html.Div() auth.config['permissions_cache_expiry'] = 30 auth.create_access_codes() viewer_token = users['viewer']['oauth_token'] with mock.patch('dash_auth.plotly_auth.check_view_access', wraps=plotly_auth.check_view_access) as \ wrapped: n_endpoints = (len(endpoints['protected']['get']) + len(endpoints['unprotected']['get'])) # sanity check the endpoints when the app is private self.check_endpoints(auth, app, viewer_token) self.assertEqual(wrapped.call_count, n_endpoints) # make app public dash_auth.plotly_auth.create_or_overwrite_dash_app( app_name, 'public', app_url) res = self.check_endpoints(auth, app, viewer_token, all_200=True) self.assertEqual(wrapped.call_count, n_endpoints * 2) # The last access granted response contained a cookie that grants # the user access for 30 seconds (5 minutes by default) # without making an API call to plotly. # Include this cookie in the response and verify that it grants # the user access up until the expiration date access_granted_cookie = get_cookie(res, PlotlyAuth.AUTH_COOKIE_NAME) self.assertEqual(access_granted_cookie, auth._access_codes['access_granted']) plotly_auth.create_or_overwrite_dash_app(app_name, 'private', app_url) # Even though the app is private, the viewer will still get 200s access_cookie = ({ 'name': PlotlyAuth.AUTH_COOKIE_NAME, 'value': access_granted_cookie }, ) self.check_endpoints(auth, app, viewer_token, access_cookie, all_200=True) self.assertEqual(wrapped.call_count, n_endpoints * 2) # But after 30 seconds, the auth token will expire, # and the user will be denied access time.sleep(5) self.check_endpoints(auth, app, viewer_token, access_cookie, all_200=True) self.assertEqual(wrapped.call_count, n_endpoints * 2) time.sleep(26) self.check_endpoints(auth, app, viewer_token, access_cookie) self.assertEqual(wrapped.call_count, n_endpoints * 3)