From f5213c24efbb8ca3b35a1aaf23aa4e88b6bf36d1 Mon Sep 17 00:00:00 2001 From: st4lk Date: Wed, 27 May 2015 14:30:03 +0300 Subject: [PATCH] add manual redirect_uri --- README.md | 9 +++++++++ rest_social_auth/serializers.py | 1 + rest_social_auth/views.py | 18 +++++++++++++----- tests/test_social.py | 10 ++++++++++ 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f3939bf..3429313 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,12 @@ Quick start User model is taken from [`settings.AUTH_USER_MODEL`](https://docs.djangoproject.com/en/dev/topics/auth/customizing/#substituting-a-custom-user-model). + At input there is also non-required field `redirect_uri`. + If given, server will use this redirect uri in requests, instead of uri + got from settings. + This redirect_uri must be equal in front-end request and in back-end request. + Back-end will not do any redirect in fact. + OAuth 2.0 workflow with rest-social-auth ----------------------------------------- @@ -224,6 +230,9 @@ Settings REST_SOCIAL_OAUTH_ABSOLUTE_REDIRECT_URI = 'http://myproject.com/' + This settings has higher priority than `REST_SOCIAL_OAUTH_REDIRECT_URI`. + Also, `redirect_uri` from request has higher priority than any setting. + Customization diff --git a/rest_social_auth/serializers.py b/rest_social_auth/serializers.py index 99e6f5b..d35abc2 100644 --- a/rest_social_auth/serializers.py +++ b/rest_social_auth/serializers.py @@ -7,6 +7,7 @@ class SocialAuthInputSerializer(serializers.Serializer): provider = serializers.CharField() code = serializers.CharField() + redirect_uri = serializers.URLField(required=False) class UserSerializer(serializers.ModelSerializer): diff --git a/rest_social_auth/views.py b/rest_social_auth/views.py index 46e45db..7809a2b 100644 --- a/rest_social_auth/views.py +++ b/rest_social_auth/views.py @@ -26,10 +26,9 @@ def load_strategy(request=None): @psa(REDIRECT_URI, load_strategy=load_strategy) def register_by_auth_token(request, backend, *args, **kwargs): user = request.user - absolute_redirect_uri = getattr(settings, - 'REST_SOCIAL_OAUTH_ABSOLUTE_REDIRECT_URI', None) - if absolute_redirect_uri: - request.backend.redirect_uri = absolute_redirect_uri + redirect_uri = kwargs.pop('manual_redirect_uri', None) + if redirect_uri: + request.backend.redirect_uri = redirect_uri is_authenticated = user_is_authenticated(user) user = is_authenticated and user or None # skip checking state by setting following params to False @@ -73,8 +72,11 @@ def post(self, request, *args, **kwargs): serializer_in.is_valid(raise_exception=True) self.set_input_data(request, serializer_in.validated_data.copy()) provider = request.auth_data.pop('provider') + manual_redirect_uri = request.auth_data.pop('redirect_uri', None) + manual_redirect_uri = self.get_redirect_uri(manual_redirect_uri) try: - user = register_by_auth_token(request, provider) + user = register_by_auth_token(request, provider, + manual_redirect_uri=manual_redirect_uri) except AuthException as e: return self.respond_error(e, provider) resp_data = self.get_serializer_class_out()(instance=user) @@ -94,6 +96,12 @@ def set_input_data(self, request, auth_data): """ request.auth_data = auth_data + def get_redirect_uri(self, manual_redirect_uri): + if not manual_redirect_uri: + manual_redirect_uri = getattr(settings, + 'REST_SOCIAL_OAUTH_ABSOLUTE_REDIRECT_URI', None) + return manual_redirect_uri + def respond_error(self, error, provider): return Response(status=status.HTTP_400_BAD_REQUEST) diff --git a/tests/test_social.py b/tests/test_social.py index b805d84..787556a 100644 --- a/tests/test_social.py +++ b/tests/test_social.py @@ -50,6 +50,7 @@ def setUp(self): def tearDown(self): HTTPretty.disable() + HTTPretty.reset() self.backend = None self.strategy = None self.name = None @@ -96,6 +97,15 @@ def test_login_absolute_redirect(self): url_params = dict(parse_qsl(urlparse(HTTPretty.latest_requests[0].path).query)) self.assertEqual('http://myproject.com/', url_params['redirect_uri']) + @override_settings(REST_SOCIAL_OAUTH_ABSOLUTE_REDIRECT_URI='http://myproject.com/') + def test_login_manual_redirect(self): + resp = self.client.post(reverse('login_social_session'), + data={'provider': 'facebook', 'code': '3D52VoM1uiw94a1ETnGvYlCw', + 'redirect_uri': 'http://manualdomain.com/'}) + self.assertEqual(resp.status_code, 200) + url_params = dict(parse_qsl(urlparse(HTTPretty.latest_requests[0].path).query)) + self.assertEqual('http://manualdomain.com/', url_params['redirect_uri']) + class TestSocialAuthError(APITestCase, BaseFacebookAPITestCase): access_token_status = 400