Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip authorisation After First Consent (#112) #128

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions omniport/core/open_auth/http_urls.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
from django.urls import path, include
from django.views.decorators.http import require_POST
from oauth2_provider.views import (
AuthorizationView,
TokenView,
RevokeTokenView,
)
from rest_framework import routers

from open_auth.views.application import ApplicationViewSet
from open_auth.views.application import ApplicationViewSet, OmniportAuthorizationView
from open_auth.views.retrieve_data import GetUserData

router = routers.SimpleRouter()
Expand All @@ -18,7 +17,7 @@
urlpatterns = [
path(
'authorise/',
require_POST(AuthorizationView.as_view()),
require_POST(OmniportAuthorizationView.as_view()),
name='authorise'
),
path(
Expand Down
1 change: 1 addition & 0 deletions omniport/core/open_auth/serializers/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class Meta:

model = Application
fields = [
'id',
'client_id',
'redirect_uris',
'name',
Expand Down
104 changes: 104 additions & 0 deletions omniport/core/open_auth/views/application.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
from rest_framework import viewsets, mixins, permissions
from rest_framework.decorators import action
from django.http import HttpResponse
from oauth2_provider.exceptions import OAuthToolkitError
from oauth2_provider.models import get_application_model,get_access_token_model
from oauth2_provider.scopes import get_scopes_backend
from oauth2_provider.settings import oauth2_settings
from oauth2_provider.views import AuthorizationView

from open_auth.models import Application
from open_auth.serializers.application import ApplicationAuthoriseSerializer
Expand All @@ -17,3 +24,100 @@ class ApplicationViewSet(
queryset = Application.objects.filter(is_approved=True)
lookup_field = 'client_id'
pagination_class = None

@action(methods=['get'], detail=False, url_name="get_token", url_path="get_token")
def get_token(self, request):
"""
Action view for getting the availabilty of token
for a particular view in order to skip authorization
after first consent
"""

token=get_access_token_model().objects.filter(
user=request.user,
application=request.GET.get('id')
).exists()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please leave exactly one newline between blocks of code and two lines between functions and classes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have made the changes. Please review

return HttpResponse(token)


class OmniportAuthorizationView(AuthorizationView):
"""
Overrided the default implementation
of get method of AuthorizationView in order
to skip authorization even after the access
token has expired.
"""

def get(self, request, *args, **kwargs):
"""
The code is similar to https://github.com/jazzband/django-oauth-toolkit/blob/master/oauth2_provider/views/base.py
Significant Changes marked with *** in the code
"""

try:
require_approval = request.GET.get(
"approval_prompt",
oauth2_settings.REQUEST_APPROVAL_PROMPT,
)

if require_approval != 'auto_even_if_expired':
return super(OmniportAuthorizationView, self).get(request, *args, **kwargs)

scopes, credentials = self.validate_authorization_request(request)
all_scopes = get_scopes_backend().get_all_scopes()
kwargs["scopes_descriptions"] = [all_scopes[scope] for scope in scopes]
kwargs['scopes'] = scopes
# at this point we know an Application instance with such client_id exists in the database

application = get_application_model().objects.get(client_id=credentials['client_id'])

kwargs['application'] = application
kwargs['client_id'] = credentials['client_id']
kwargs['redirect_uri'] = credentials['redirect_uri']
kwargs['response_type'] = credentials['response_type']
kwargs['state'] = credentials['state']

self.oauth2_data = kwargs
# following two loc are here only because of https://code.djangoproject.com/ticket/17795
form = self.get_form(self.get_form_class())
kwargs['form'] = form


#If skip_authorization field is True, skip the authorization screen even
#if this is the first use of the application and there was no previous authorization.
#This is useful for in-house applications-> assume an in-house applications
#re already approved.
if application.skip_authorization:
uri, headers, body, status = self.create_authorization_response(
request=self.request, scopes=" ".join(scopes),
credentials=credentials, allow=True)
return self.redirect(uri, application)

#check for require_approval
assert require_approval == 'auto_even_if_expired'

tokens = (
get_access_token_model()
.objects.filter(
user=request.user,
application=kwargs["application"],
#expires__gt=timezone.now(), ***
)
.all()
)

# check past authorizations regarded the same scopes as the current one
for token in tokens:
if token.allow_scopes(scopes):
uri, headers, body, status = self.create_authorization_response(
request=self.request, scopes=" ".join(scopes),
credentials=credentials, allow=True)
return self.redirect(uri, application)

# render an authorization prompt so the user can approve
# the application's requested scopes
return self.render_to_response(self.get_context_data(**kwargs))

except OAuthToolkitError as error:
return self.error_response(error)
3 changes: 3 additions & 0 deletions omniport/omniport/settings/base/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,6 @@
SESSION_COOKIE_NAME = 'omniport_session'

OAUTH2_PROVIDER_APPLICATION_MODEL = 'open_auth.Application'
OAUTH2_PROVIDER={
'REQUEST_APPROVAL_PROMPT':'auto_even_if_expired',
}