Closed brylie closed 5 years ago
One fleeting thought might be to create a sub-class of DjangoDash
, and use a mixin to enforce access control. This would probably require additions to the DjangoDash class. Taking this thought a bit further, perhaps DjangoDash
could inherit from one of the django built-in class-based views?
Been thinking about this myself. I haven't managed to solve this yet generically but I guess it isn't a problem exclusive to DPD. Perhaps checking authentication in the middleware for all dash apps is an option so that nothing no views can render before authentication and authorization has occurred.
There is this configuration option which allows you to specify a function to call on every dash method invocation. This could be as simple as the existing login_required
provided by Django or something more sophisticated.
There is a related discussion in #56 also.
@delsim would that work for users who know the direct link to the iframe src?
It should do, as all the iframe will do is use the django-plotly-dash urls, and if they are wrapped in some form of protection it doesn't matter where the request comes from.
My concern, which may be based on the wrong assumption, is that the django_plotly_dash
view function may not use any access control decorators, even though my template view would use access control. So, by directly linking to the iframe source URL, a user could bypass access control, auditing, etc:
In this regard, the plotly_direct
template tag would seem like the safer bet, since the dashboard is rendered directly into the (decorated) view template.
Resolution of #82 will hopefully help.
I am able to confirm my suspicion that Dash views are not secured, even though the django view might use access control (such as @login_required
). Steps to reproduce:
@login_required
to django viewdjango_plotly_dash/app/<app-name>/_dash-layout
The Dash layout object can be viewed in full, including any possibly sensitive data.
For clarification, we are using Dash for internal dashboards, and want to be really cautious about user data, particularly in light of GDPR and respecting user privacy.
@brylie is this using an iframe or when returned as html? Or either? I will try this tomorrow
I am surprised this occurs given the @login_required decorator. Perhaps the middleware is a better option. I will also try this option tomorrow.
Are you setting the PLOTLY_DASH.view_decorator
option? If not then you would need to wrap pretty much all of the routes in the urls.py file.
In advance of the still-to-be written documentation (#82) a value of django_plotly_dash.access.login_required
should make all dash apps require authentication.
Are you setting the PLOTLY_DASH.view_decorator option?
Yes, I have the following in my settings.py
:
from django.contrib.auth.decorators import login_required
PLOTLY_DASH = {
# Name of view wrapping function
"view_decorator": login_required,
}
Thanks for clarifying the documentation-in-progress. It should also be mentioned that I would like to support specific access control rules per view, perhaps using group based access control. I.e. not all users should have access to all data/views, so simply checking login_required
will not likely be sufficient.
is this using an iframe or when returned as html? Or either? I will try this tomorrow
@eddy-ojb I have tested the above scenario with plotly_direct
, and then using the Chrome page inspector to get the XHR paths:
{% block dashboard %}
{% plotly_direct name="TopUsers"%}
{% endblock dashboard %}
When I switch the template to use plotly_app
, I am still able to access the iframe content directly as an anonymous user, by copying the value from src
attiribute and pasting it in an incognito tab:
{% block dashboard %}
{% plotly_app name="TopUsers"%}
{% endblock dashboard %}
Are you able to try this:
PLOTLY_DASH = {
# Name of view wrapping function
"view_decorator": "django_plotly_dash.access.login_required",
}
Ah, sorry I overlooked that in your previous comment. I will try ASAP.
It would also be useful to know how to write custom access functions, so that I can, for example, check for group membership or other criteria before users can access a Dash view. Also, it would be good to share these authorization functions between the Dash and django view, for DRY code.
Just pulled #90 into master, which hopefully addresses this, and closing this issue. Please reopen with comments if the documentation can be improved.
@GibbsConsulting does the login_required
decorator prevent someone from directly accessing the underlying Dash app that is embedded via the IFrame? For example, say an authorized user logs in and copies the Dash app IFrame link and share it with an unauthorized person. Would that unauthorized person be able to use the direct link to the access Dash app, bypassing the Django access control?
I just want to be really clear here, because we are again looking at Django Plotly Dash as an alternative to Tableau.
@brylie The function supplied as the view_decorator
should get called on every call that passes through django_plotly_dash
, so you should not be able to subvert the access control by copying the link.
You can verify this by doing exactly as you describe - go to an app as an authorized user, grab one of the urls (the debugging console of your browser can help you do this), and then try to access that url as an unauthorized user.
@brylie @GibbsConsulting I am running into a similar issue during penetration testing regarding the accessibility of underlying data via iframe URL.
Azure Active Directory was used to wrap all views in my core django project, and I have also passed a view decorator in PLOTLY_DASH as specified above. Would you be able to share how you implemented it?
@jeffamaxey can you describe the particular issue you're facing? Ideally by opening a new issue as that would be easier to track.
When using the
dash_app
template tag, the contents are rendered in an iframe. A curious user can inspect the page source and get the direct link to the Dash app directly form the iframe. The direct link might allow the user to bypass access control and other precautions built into a project. This seems to undermine the view based access control:How can we mitigate the risk of potential abuse, particularly when dashboards may contain sensitive data?