Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Securing Django OAuth Toolkit Views

We're looking to implement Django OAuth on our backend in order to integrate Alexa and other 3rd party APIs. We've been following the tutorials on their site (http://django-oauth-toolkit.readthedocs.io/en/latest/tutorial/tutorial.html), but have run into a security question that has so far escaped us:

Is there a security concern that any user can access https://<oursite.com>/o/applications? If so, what steps need to be taken to prevent users from accessing these views?

The only relevant questions on SO weren't particularly helpful:

Secure creation of new applications in Django OAuth Toolkit

Disable or restrict /o/applications (django rest framework, oauth2)

like image 702
Nat Homer Avatar asked Nov 17 '16 22:11

Nat Homer


2 Answers

I'm doing a similar thing, and I believe it is a security concern that anyone can see /o/applications - from what I can tell, that page is meant to be a development utility, not a production page. In fact, in the django-oauth-toolkit documentation, they have a code example with more restricted access to views.

from django.conf.urls import url
import oauth2_provider.views as oauth2_views
from django.conf import settings
from .views import ApiEndpoint

# OAuth2 provider endpoints
oauth2_endpoint_views = [
    url(r'^authorize/$', oauth2_views.AuthorizationView.as_view(), name="authorize"),
    url(r'^token/$', oauth2_views.TokenView.as_view(), name="token"),
    url(r'^revoke-token/$', oauth2_views.RevokeTokenView.as_view(), name="revoke-token"),
]

if settings.DEBUG:
    # OAuth2 Application Management endpoints
    oauth2_endpoint_views += [
        url(r'^applications/$', oauth2_views.ApplicationList.as_view(), name="list"),
        url(r'^applications/register/$', oauth2_views.ApplicationRegistration.as_view(), name="register"),
        url(r'^applications/(?P<pk>\d+)/$', oauth2_views.ApplicationDetail.as_view(), name="detail"),
        url(r'^applications/(?P<pk>\d+)/delete/$', oauth2_views.ApplicationDelete.as_view(), name="delete"),
        url(r'^applications/(?P<pk>\d+)/update/$', oauth2_views.ApplicationUpdate.as_view(), name="update"),
    ]

    # OAuth2 Token Management endpoints
    oauth2_endpoint_views += [
        url(r'^authorized-tokens/$', oauth2_views.AuthorizedTokensListView.as_view(), name="authorized-token-list"),
        url(r'^authorized-tokens/(?P<pk>\d+)/delete/$', oauth2_views.AuthorizedTokenDeleteView.as_view(),
            name="authorized-token-delete"),
    ]

urlpatterns = [
    # OAuth 2 endpoints:
    url(r'^o/', include(oauth2_endpoint_views, namespace="oauth2_provider")),

    url(r'^admin/', include(admin.site.urls)),
    url(r'^api/hello', ApiEndpoint.as_view()),  # an example resource endpoint
]

The revoke token view is part of the RFC, so that one is needed. I took a similar approach in my app of only including AuthorizationView, TokenView, and RevokeTokenView.

Hope that helps!

like image 148
Noah Gilmore Avatar answered Sep 21 '22 10:09

Noah Gilmore


It is a security concern, and I suggest restricting access only to superusers with active accounts as in the following code from urls.py:

from django.contrib.auth.decorators import user_passes_test
import oauth2_provider.views as oauth2_views

def is_super(user):
    return user.is_superuser and user.is_active

oauth2_endpoint_views = [
    url(r'^authorize/$', oauth2_views.AuthorizationView.as_view(), name="authorize"),
    url(r'^token/$', oauth2_views.TokenView.as_view(), name="token"),
    url(r'^revoke-token/$', oauth2_views.RevokeTokenView.as_view(), name="revoke-token"),
    # the above are public but we restrict the following:
    url(r'^applications/$', user_passes_test(is_super)(oauth2_views.ApplicationList.as_view()), name="list"),
    ...
]
urlpatterns = [url(r'^o/', include(oauth2_endpoint_views, namespace="oauth2_provider"))]
like image 40
David Chandler Avatar answered Sep 20 '22 10:09

David Chandler