From: Jan Szejko Date: Fri, 20 Apr 2018 13:03:58 +0000 (+0200) Subject: simplify piston authorize form X-Git-Url: https://git.mdrn.pl/wolnelektury.git/commitdiff_plain/67552e19bc548b78c18967e97f0c0328074a3576 simplify piston authorize form --- diff --git a/src/api/piston_patch.py b/src/api/piston_patch.py new file mode 100644 index 000000000..4bf9b615d --- /dev/null +++ b/src/api/piston_patch.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- + +# modified from django-piston +import base64 +import hmac + +from django import forms +from django.conf import settings +from django.contrib.auth.decorators import login_required +from django.core.urlresolvers import get_callable +from django.http import HttpResponseRedirect, HttpResponse +from django.shortcuts import render_to_response +from django.template.context import RequestContext +from piston import oauth +from piston.authentication import initialize_server_request, INVALID_PARAMS_RESPONSE, send_oauth_error + + +class OAuthAuthenticationForm(forms.Form): + oauth_token = forms.CharField(widget=forms.HiddenInput) + oauth_callback = forms.CharField(widget=forms.HiddenInput) # changed from URLField - too strict + # removed authorize_access - redundant + csrf_signature = forms.CharField(widget=forms.HiddenInput) + + def __init__(self, *args, **kwargs): + forms.Form.__init__(self, *args, **kwargs) + + self.fields['csrf_signature'].initial = self.initial_csrf_signature + + def clean_csrf_signature(self): + sig = self.cleaned_data['csrf_signature'] + token = self.cleaned_data['oauth_token'] + + sig1 = OAuthAuthenticationForm.get_csrf_signature(settings.SECRET_KEY, token) + + if sig != sig1: + raise forms.ValidationError("CSRF signature is not valid") + + return sig + + def initial_csrf_signature(self): + token = self.initial['oauth_token'] + return OAuthAuthenticationForm.get_csrf_signature(settings.SECRET_KEY, token) + + @staticmethod + def get_csrf_signature(key, token): + # Check signature... + import hashlib # 2.5 + hashed = hmac.new(key, token, hashlib.sha1) + + # calculate the digest base 64 + return base64.b64encode(hashed.digest()) + + +# The only thing changed in the views below is the form used + + +def oauth_auth_view(request, token, callback, params): + form = OAuthAuthenticationForm(initial={ + 'oauth_token': token.key, + 'oauth_callback': callback, + }) + + return render_to_response('piston/authorize_token.html', + {'form': form}, RequestContext(request)) + + +@login_required +def oauth_user_auth(request): + oauth_server, oauth_request = initialize_server_request(request) + + if oauth_request is None: + return INVALID_PARAMS_RESPONSE + + try: + token = oauth_server.fetch_request_token(oauth_request) + except oauth.OAuthError, err: + return send_oauth_error(err) + + try: + callback = oauth_server.get_callback(oauth_request) + except: + callback = None + + if request.method == "GET": + params = oauth_request.get_normalized_parameters() + + oauth_view = getattr(settings, 'OAUTH_AUTH_VIEW', None) + if oauth_view is None: + return oauth_auth_view(request, token, callback, params) + else: + return get_callable(oauth_view)(request, token, callback, params) + elif request.method == "POST": + try: + form = OAuthAuthenticationForm(request.POST) + if form.is_valid(): + token = oauth_server.authorize_token(token, request.user) + args = '?' + token.to_string(only_key=True) + else: + args = '?error=%s' % 'Access not granted by user.' + + if not callback: + callback = getattr(settings, 'OAUTH_CALLBACK_VIEW') + return get_callable(callback)(request, token) + + response = HttpResponseRedirect(callback + args) + + except oauth.OAuthError, err: + response = send_oauth_error(err) + else: + response = HttpResponse('Action not allowed.') + + return response diff --git a/src/api/urls.py b/src/api/urls.py index 22c8249e3..29e7a752f 100644 --- a/src/api/urls.py +++ b/src/api/urls.py @@ -2,14 +2,16 @@ # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # -from django.conf.urls import patterns, url +from django.conf.urls import url from django.views.decorators.csrf import csrf_exempt from django.views.generic import TemplateView -from piston.authentication import OAuthAuthentication, oauth_access_token +from piston.authentication import OAuthAuthentication, oauth_access_token, oauth_request_token from piston.resource import Resource from ssify import ssi_included +import catalogue.views from api import handlers from api.helpers import CsrfExemptResource +from api.piston_patch import oauth_user_auth auth = OAuthAuthentication(realm="Wolne Lektury") @@ -50,21 +52,18 @@ def incl(request, model, pk, emitter_format): return resp -urlpatterns = patterns( - 'piston.authentication', - url(r'^oauth/request_token/$', 'oauth_request_token'), - url(r'^oauth/authorize/$', 'oauth_user_auth'), +urlpatterns = [ + url(r'^oauth/request_token/$', oauth_request_token), + url(r'^oauth/authorize/$', oauth_user_auth, name='oauth_user_auth'), url(r'^oauth/access_token/$', csrf_exempt(oauth_access_token)), -) + patterns( - '', url(r'^$', TemplateView.as_view(template_name='api/main.html'), name='api'), url(r'^include/(?Pbook|fragment|tag)/(?P\d+)\.(?P.+)\.(?Pxml|json)$', incl, name='api_include'), # info boxes (used by mobile app) - url(r'book/(?P\d*?)/info\.html$', 'catalogue.views.book_info'), - url(r'tag/(?P\d*?)/info\.html$', 'catalogue.views.tag_info'), + url(r'book/(?P\d*?)/info\.html$', catalogue.views.book_info), + url(r'tag/(?P\d*?)/info\.html$', catalogue.views.tag_info), # books by collections url(r'^collections/$', collection_list_resource, name="api_collections"), @@ -103,4 +102,4 @@ urlpatterns = patterns( # tags by category url(r'^(?P[a-z0-9-]+)/$', tag_list_resource, name='api_tag_list'), -) +] diff --git a/src/wolnelektury/templates/piston/authorize_token.html b/src/wolnelektury/templates/piston/authorize_token.html index 03131c713..e54f70136 100755 --- a/src/wolnelektury/templates/piston/authorize_token.html +++ b/src/wolnelektury/templates/piston/authorize_token.html @@ -11,7 +11,7 @@ {% blocktrans %}Confirm to authorize access to Wolne Lektury as user {{ user}}.{% endblocktrans %}

-
+ {% csrf_token %} {{ form.as_p }}