From f5f79968fe5ea944e7bca3a99e13d2494f2e7962 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 19 Nov 2013 01:57:03 +0100 Subject: [PATCH 1/2] add support for builtin login to the authorization form and add AuthorizationLoginView which enables it --- oauth2_provider/forms.py | 4 ++ .../templates/oauth2_provider/authorize.html | 38 ++++++++++--- oauth2_provider/views/base.py | 55 ++++++++++++++++--- 3 files changed, 83 insertions(+), 14 deletions(-) diff --git a/oauth2_provider/forms.py b/oauth2_provider/forms.py index f506d8a1e..f98099755 100644 --- a/oauth2_provider/forms.py +++ b/oauth2_provider/forms.py @@ -11,6 +11,10 @@ class AllowForm(forms.Form): state = forms.CharField(required=False, widget=forms.HiddenInput()) response_type = forms.CharField(widget=forms.HiddenInput()) +from django.contrib.auth.forms import AuthenticationForm + +class AllowLoginForm(AuthenticationForm,AllowForm): pass + class RegistrationForm(forms.ModelForm): """ diff --git a/oauth2_provider/templates/oauth2_provider/authorize.html b/oauth2_provider/templates/oauth2_provider/authorize.html index 6e6a2a93e..ef3c28c1c 100644 --- a/oauth2_provider/templates/oauth2_provider/authorize.html +++ b/oauth2_provider/templates/oauth2_provider/authorize.html @@ -8,11 +8,21 @@

{% trans "Authorize" %} {{ application.name }}?

{% csrf_token %} - {% for field in form %} - {% if field.is_hidden %} - {{ field }} - {% endif %} - {% endfor %} + {% for hidden in form.hidden_fields %}{{ hidden }}{% endfor %} + + {% if form.errors %} +

+ {% if form.errors.items|length == 1 %}{% trans "Please correct the error below." %}{% else %}{% trans "Please correct the errors below." %}{% endif %} +

+ {% endif %} + + {% if form.non_field_errors %} + {% for error in form.non_field_errors %} +

+ {{ error }} +

+ {% endfor %} + {% endif %}

{% trans "Application requires following permissions" %}

- {{ form.errors }} - {{ form.non_field_errors }} + {% if require_login %} +
+ {{ form.username.errors }} + {{ form.username }} +
+
+ {{ form.password.errors }} + {{ form.password }} +
+ {% url 'password_reset' as password_reset_url %} + {% if password_reset_url %} + + {% endif %} + {% endif %}
diff --git a/oauth2_provider/views/base.py b/oauth2_provider/views/base.py index 3e9a31269..003fe7318 100644 --- a/oauth2_provider/views/base.py +++ b/oauth2_provider/views/base.py @@ -9,7 +9,7 @@ from ..settings import oauth2_settings from ..exceptions import OAuthToolkitError -from ..forms import AllowForm +from ..forms import AllowForm, AllowLoginForm from ..models import get_application_model from ..oauth2_validators import OAuth2Validator from .mixins import OAuthLibMixin @@ -66,6 +66,7 @@ class AuthorizationView(BaseAuthorizationView, FormView): template_name = 'oauth2_provider/authorize.html' form_class = AllowForm + builtin_login = False server_class = Server validator_class = OAuth2Validator @@ -92,6 +93,12 @@ def form_valid(self, form): scopes = form.cleaned_data.get('scopes') allow = form.cleaned_data.get('allow') + if self.builtin_login and not self.request.user.is_authenticated(): + from django.contrib.auth import login + # Okay, security check complete. Log the user in. + login(self.request, form.get_user()) + if django.VERSION[1]<6 and self.request.session.test_cookie_worked(): + self.request.session.delete_test_cookie() uri, headers, body, status = self.create_authorization_response( request=self.request, scopes=scopes, credentials=credentials, allow=allow) self.success_url = uri @@ -101,15 +108,19 @@ def form_valid(self, form): except OAuthToolkitError as error: return self.error_response(error) + def dispatch(self, request, *args, **kwargs): + from braces.views import LoginRequiredMixin + self.oauth2_data = {} + if not self.builtin_login and not request.user.is_authenticated(): + return super(AuthorizationView, self).dispatch(request, *args, **kwargs) + # skip login + return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs) + def get(self, request, *args, **kwargs): try: scopes, credentials = self.validate_authorization_request(request) - kwargs['scopes_descriptions'] = [oauth2_settings.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 - kwargs['application'] = Application.objects.get(client_id=credentials['client_id']) # TODO: cache it! - kwargs.update(credentials) - self.oauth2_data = kwargs + credentials['scopes'] = scopes # add the scopes + self.oauth2_data = credentials # following code is here only because of https://code.djangoproject.com/ticket/17795 form = self.get_form(self.get_form_class()) kwargs['form'] = form @@ -118,6 +129,36 @@ def get(self, request, *args, **kwargs): except OAuthToolkitError as error: return self.error_response(error) + def get_form_class(self): + if self.builtin_login: return AllowLoginForm + return AllowForm + + def get_form_kwargs(self): + kwargs = super(AuthorizationView, self).get_form_kwargs() + if self.builtin_login: kwargs.update({'request': self.request}) # required for login + return kwargs + + def get_context_data(self,**kwargs): + from oauth2_provider.settings import oauth2_settings + from oauth2_provider.models import get_application_model + from django import VERSION + Application = get_application_model() + kwargs = super(AuthorizationView, self).get_context_data(**kwargs) + self.request.POST = {} # validate based only on GET parameters + scopes, credentials = self.validate_authorization_request(self.request) + kwargs['scopes_descriptions'] = [oauth2_settings.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 + kwargs['application'] = Application.objects.get(client_id=credentials['client_id']) + kwargs['require_login'] = self.builtin_login and not self.request.user.is_authenticated() + kwargs.update(credentials) + if kwargs['login'] and VERSION[1]<6: + self.request.session.set_test_cookie() + return kwargs + +class AuthorizationLoginView(AuthorizationView): + builtin_login = True + class TokenView(CsrfExemptMixin, OAuthLibMixin, View): """ From 89f18340fd5c36da85b8164fed855f05ea58a106 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 19 Nov 2013 02:10:41 +0100 Subject: [PATCH 2/2] minor fix --- oauth2_provider/views/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oauth2_provider/views/base.py b/oauth2_provider/views/base.py index 003fe7318..d3f110187 100644 --- a/oauth2_provider/views/base.py +++ b/oauth2_provider/views/base.py @@ -152,7 +152,7 @@ def get_context_data(self,**kwargs): kwargs['application'] = Application.objects.get(client_id=credentials['client_id']) kwargs['require_login'] = self.builtin_login and not self.request.user.is_authenticated() kwargs.update(credentials) - if kwargs['login'] and VERSION[1]<6: + if kwargs['require_login'] and VERSION[1]<6: self.request.session.set_test_cookie() return kwargs