diff --git a/docs/api_endpoints.rst b/docs/api_endpoints.rst index 05e8691..1b55bb3 100644 --- a/docs/api_endpoints.rst +++ b/docs/api_endpoints.rst @@ -73,3 +73,4 @@ Basing on example from installation section :doc:`Installation ` - /rest-auth/facebook/ (POST) - access_token + - code diff --git a/rest_auth/registration/serializers.py b/rest_auth/registration/serializers.py index 2de467e..158e6ca 100644 --- a/rest_auth/registration/serializers.py +++ b/rest_auth/registration/serializers.py @@ -9,15 +9,17 @@ class SocialLoginSerializer(serializers.Serializer): access_token = serializers.CharField(required=True) def validate(self, attrs): - access_token = attrs.get('access_token') + view = self.context.get('view') request = self.context.get('request') if not isinstance(request, HttpRequest): request = request._request if not view: - raise serializers.ValidationError('View is not defined, pass it ' + - 'as a context variable') + raise serializers.ValidationError( + 'View is not defined, pass it ' + + 'as a context variable' + ) self.adapter_class = getattr(view, 'adapter_class', None) if not self.adapter_class: @@ -25,6 +27,32 @@ class SocialLoginSerializer(serializers.Serializer): self.adapter = self.adapter_class() app = self.adapter.get_provider().get_app(request) + + # More info on code vs access_token + # http://stackoverflow.com/questions/8666316/facebook-oauth-2-0-code-and-token + # We have the access_token straight + if('access_token' in attrs): + access_token = attrs.get('access_token') + # We did not get the access_token, but authorization code instead + elif('code' in attrs): + code = attrs.get('code') + + callback_url = self.callback_url + + provider = self.adapter.get_provider() + scope = provider.get_scope(request) + client = self.adapter_class( + request, + app.client_id, + app.secret, + self.adapter.access_token_method, + self.adapter.access_token_url, + callback_url, + scope + ) + token = client.get_access_token(code) + access_token = token['access_token'] + token = self.adapter.parse_token({'access_token': access_token}) token.app = app diff --git a/rest_auth/registration/views.py b/rest_auth/registration/views.py index 485881c..ab9c705 100644 --- a/rest_auth/registration/views.py +++ b/rest_auth/registration/views.py @@ -72,11 +72,25 @@ class VerifyEmail(APIView, ConfirmEmailView): class SocialLogin(Login): """ class used for social authentications - example usage for facebook + example usage for facebook with access_token + ------------- from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter + class FacebookLogin(SocialLogin): adapter_class = FacebookOAuth2Adapter + + ------------- + example usage for facebook with code + + from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter + from allauth.socialaccount.providers.oauth2.client import OAuth2Client + + class FacebookLogin(SocialLogin): + adapter_class = FacebookOAuth2Adapter + client_class = OAuth2Client + callback_url = 'localhost:8000' + ------------- """ serializer_class = SocialLoginSerializer