{"id":7766,"date":"2015-10-23T15:59:15","date_gmt":"2015-10-23T15:59:15","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2015\/10\/23\/facebook-auth-with-angularjs-and-django-rest-framework-open-source-projects-tomchristie-django-rest-framework\/"},"modified":"2015-10-23T15:59:15","modified_gmt":"2015-10-23T15:59:15","slug":"facebook-auth-with-angularjs-and-django-rest-framework-open-source-projects-tomchristie-django-rest-framework","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2015\/10\/23\/facebook-auth-with-angularjs-and-django-rest-framework-open-source-projects-tomchristie-django-rest-framework\/","title":{"rendered":"Facebook Auth with AngularJS and Django REST Framework-open source projects tomchristie\/django-rest-framework"},"content":{"rendered":"<p>I am developing a SPA application with AngularJS which uses Django backend for the server. The way that I communicate with the server from the SPA is with django-rest-framework. So now I want to make authentication with facebook (google and twitter too) and I read a lot on this topic and found OAuth.io which is making the authetication on the client SPA side and python-social-auth which is doing the same thing but on the server side.<\/p>\n<p>So currently I have only the client auth, my app is connecting to facebook (with OAuth.io) and login successfully. This process is returning access_token and then I am making a request to my API which have to login this user or create account for this user by given token and this part is not working. So I am not sure where I am wrong, maybe because there isn&#8217;t a full tutorial about using python-social-auth so maybe I am missing something or.. I don&#8217;t know..<\/p>\n<p>So some code of this what I have:<\/p>\n<p>On the SPA side: This is the connection with OAuth.io and is working because I am getting the access token. Then I have to make a request to my rest API. backend is &#8216;facebook&#8217;, &#8216;google&#8217; or &#8216;twitter&#8217;<\/p>\n<pre><code>OAuth.initialize('my-auth-code-for-oauthio');\nOAuth.popup(backend, function(error, result) {\n    \/\/handle error with error\n    \/\/use result.access_token in your API request\n\n    var token = 'Token ' + result.access_token;\n    var loginPromise = $http({\n         method:'POST', \n         url: 'api-token\/login\/' + backend + '\/', \n         headers: {'Authorization': token}});\n\n         loginPromise.success(function () {\n             console.log('Succeess');\n         });\n         loginPromise.error(function (result) {\n             console.log('error');\n         });\n});\n<\/code><\/pre>\n<p>On the server in my settings.py I have added social plugin to the installed apps, template context preprocessors, some auth backends and that is my file:<\/p>\n<pre><code>INSTALLED_APPS = (\n    'django.contrib.auth',\n    'django.contrib.contenttypes',\n    'django.contrib.sessions',\n    ...,\n    'rest_framework',\n    'rest_framework.authtoken',\n    'api',\n    'social.apps.django_app.default',\n    'social'\n)\nTEMPLATE_CONTEXT_PROCESSORS = (\"django.contrib.auth.context_processors.auth\",\n                               \"django.core.context_processors.debug\",\n                               \"django.core.context_processors.i18n\",\n                               \"django.core.context_processors.media\",\n                               \"django.core.context_processors.static\",\n                               \"django.core.context_processors.request\",\n                               \"django.contrib.messages.context_processors.messages\",\n                               'social.apps.django_app.context_processors.backends',\n                               'social.apps.django_app.context_processors.login_redirect',)\n\nREST_FRAMEWORK = {\n    'DEFAULT_AUTHENTICATION_CLASSES': (\n        'rest_framework.authentication.TokenAuthentication',\n    )\n}\n\nSOCIAL_AUTH_FACEBOOK_KEY = 'key'\nSOCIAL_AUTH_FACEBOOK_SECRET = 'secret'\nSOCIAL_AUTH_FACEBOOK_SCOPE = ['email']\n\nAUTHENTICATION_BACKENDS = (\n      'social.backends.open_id.OpenIdAuth',\n      'social.backends.facebook.FacebookOAuth2',\n      'social.backends.facebook.FacebookAppOAuth',\n      'social.backends.google.GoogleOpenId',\n      'social.backends.google.GoogleOAuth2',\n      'social.backends.google.GoogleOAuth',\n      'social.backends.twitter.TwitterOAuth',\n      'django.contrib.auth.backends.ModelBackend',\n  )\n<\/code><\/pre>\n<p>In my views.py of the API I have the following (I found it here):<\/p>\n<pre><code>from django.contrib.auth.models import User, Group\nfrom rest_framework import viewsets, generics\nfrom rest_framework.views import APIView\nfrom rest_framework.response import Response\nfrom rest_framework import authentication, permissions, parsers, renderers\nfrom rest_framework.authtoken.serializers import AuthTokenSerializer\nfrom rest_framework.decorators import api_view, throttle_classes\nfrom social.apps.django_app.utils import strategy\nfrom rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly\n\nfrom django.contrib.auth import get_user_model\nfrom django.db.models.signals import post_save\nfrom django.dispatch import receiver\nfrom rest_framework.authtoken.models import Token\n\nclass ObtainAuthToken(APIView):\n    throttle_classes = ()\n    permission_classes = ()\n    parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)\n    renderer_classes = (renderers.JSONRenderer,)\n    serializer_class = AuthTokenSerializer\n    model = Token\n\n    # Accept backend as a parameter and 'auth' for a login \/ pass\n    def post(self, request, backend):\n        serializer = self.serializer_class(data=request.DATA)\n\n        if backend == 'auth':\n            if serializer.is_valid():\n                token, created = Token.objects.get_or_create(user=serializer.object['user'])\n                return Response({'token': token.key})\n            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)\n\n        else:\n            # Here we call PSA to authenticate like we would if we used PSA on server side.\n            user = register_by_access_token(request, backend)\n\n            # If user is active we get or create the REST token and send it back with user data\n            if user and user.is_active:\n                token, created = Token.objects.get_or_create(user=user)\n                return Response({'id': user.id , 'name': user.username, 'userRole': 'user','token': token.key})\n\n@strategy()\ndef register_by_access_token(request, backend):\n    backend = request.strategy.backend\n    user = request.user\n    user = backend._do_auth(\n        access_token=request.GET.get('access_token'),\n        user=user.is_authenticated() and user or None\n    )\n    return user\n<\/code><\/pre>\n<p>And finally I have these routes in urls.py:<\/p>\n<pre><code>...\nurl(r'^api-auth\/', include('rest_framework.urls', namespace='rest_framework')),\nurl(r'^api-token-auth\/', 'rest_framework.authtoken.views.obtain_auth_token'),\nurl(r'^api-token\/login\/(?P[^\/]+)\/$', views.ObtainAuthToken.as_view()),\nurl(r'^register\/(?P[^\/]+)\/', views.register_by_access_token),\n...\n<\/code><\/pre>\n<p>Everytime when I try to do auth, OAuth.io is working and the rqest to api returns<\/p>\n<blockquote>\n<p>detail: &#8220;Invalid token&#8221;<\/p>\n<\/blockquote>\n<p>I think that I missed something in the configuration of python-social-auth or I am doing everything wrong. So I will be glad if anyone has some ideas and want to help \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I am developing a SPA application with AngularJS which uses Django backend for the server. The way that I communicate with the server from the SPA is with django-rest-framework. So now I want to make authentication with facebook (google and twitter too) and I read a lot on this topic and found OAuth.io which is [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-7766","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/7766","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=7766"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/7766\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=7766"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=7766"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=7766"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}