Facebook的身份验证与AngularJS和Django的REST框架 [英] Facebook Auth with AngularJS and Django REST Framework

查看:732
本文介绍了Facebook的身份验证与AngularJS和Django的REST框架的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发展与 AngularJS 一个SPA的应用程序,它使用的Django 后端服务器。我从SPA服务器通信的方法是使用 Django的休息框架。所以现在我想和Facebook的身份验证(谷歌和Twitter太)和我读了这个话题很多,发现 OAuth.io 它正在在客户端的SPA和authetication 蟒蛇 - 社会 - AUTH 这是做同样的事情,但在服务器端

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.

所以目前我只在客户端身份验证,我的应用程序连接至Facebook(与OAuth.io),并成功登录。这个过程被返回的access_token,然后我让我的API请求具有登录该用户或该用户创建账户由下式给出令牌,这部分是行不通的。所以,我不知道我在哪里错了,也许是因为没有关于使用python-社会AUTH一个完整的教程,所以也许我失去了一些东西,或..我不知道..

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't a full tutorial about using python-social-auth so maybe I am missing something or.. I don't know..

所以这一些code我有什么:

So some code of this what I have:

在SPA的一面:这是OAuth.io连接和工作,因为我收到访问令牌。然后,我要对我的REST API的请求。后端的Facebook,谷歌或微博

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 'facebook', 'google' or 'twitter'

OAuth.initialize('my-auth-code-for-oauthio');
OAuth.popup(backend, function(error, result) {
    //handle error with error
    //use result.access_token in your API request

    var token = 'Token ' + result.access_token;
    var loginPromise = $http({
         method:'POST', 
         url: 'api-token/login/' + backend + '/', 
         headers: {'Authorization': token}});

         loginPromise.success(function () {
             console.log('Succeess');
         });
         loginPromise.error(function (result) {
             console.log('error');
         });
});

在我的settings.py服务器我加入的社交插件的安装的应用程序,模板语境preprocessors,一些权威性的后端,这是我的文件:

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:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    ...,
    'rest_framework',
    'rest_framework.authtoken',
    'api',
    'social.apps.django_app.default',
    'social'
)
TEMPLATE_CONTEXT_PROCESSORS = ("django.contrib.auth.context_processors.auth",
                               "django.core.context_processors.debug",
                               "django.core.context_processors.i18n",
                               "django.core.context_processors.media",
                               "django.core.context_processors.static",
                               "django.core.context_processors.request",
                               "django.contrib.messages.context_processors.messages",
                               'social.apps.django_app.context_processors.backends',
                               'social.apps.django_app.context_processors.login_redirect',)

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    )
}

SOCIAL_AUTH_FACEBOOK_KEY = 'key'
SOCIAL_AUTH_FACEBOOK_SECRET = 'secret'
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']

AUTHENTICATION_BACKENDS = (
      'social.backends.open_id.OpenIdAuth',
      'social.backends.facebook.FacebookOAuth2',
      'social.backends.facebook.FacebookAppOAuth',
      'social.backends.google.GoogleOpenId',
      'social.backends.google.GoogleOAuth2',
      'social.backends.google.GoogleOAuth',
      'social.backends.twitter.TwitterOAuth',
      'django.contrib.auth.backends.ModelBackend',
  )

在我,我有以下的API views.py(我发现它的这里):

In my views.py of the API I have the following (I found it here):

from django.contrib.auth.models import User, Group
from rest_framework import viewsets, generics
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions, parsers, renderers
from rest_framework.authtoken.serializers import AuthTokenSerializer
from rest_framework.decorators import api_view, throttle_classes
from social.apps.django_app.utils import strategy
from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly

from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token

class ObtainAuthToken(APIView):
    throttle_classes = ()
    permission_classes = ()
    parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
    renderer_classes = (renderers.JSONRenderer,)
    serializer_class = AuthTokenSerializer
    model = Token

    # Accept backend as a parameter and 'auth' for a login / pass
    def post(self, request, backend):
        serializer = self.serializer_class(data=request.DATA)

        if backend == 'auth':
            if serializer.is_valid():
                token, created = Token.objects.get_or_create(user=serializer.object['user'])
                return Response({'token': token.key})
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        else:
            # Here we call PSA to authenticate like we would if we used PSA on server side.
            user = register_by_access_token(request, backend)

            # If user is active we get or create the REST token and send it back with user data
            if user and user.is_active:
                token, created = Token.objects.get_or_create(user=user)
                return Response({'id': user.id , 'name': user.username, 'userRole': 'user','token': token.key})

@strategy()
def register_by_access_token(request, backend):
    backend = request.strategy.backend
    user = request.user
    user = backend._do_auth(
        access_token=request.GET.get('access_token'),
        user=user.is_authenticated() and user or None
    )
    return user

最后,我有这些航线urls.py:

And finally I have these routes in urls.py:

...
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^api-token-auth/', 'rest_framework.authtoken.views.obtain_auth_token'),
url(r'^api-token/login/(?P<backend>[^/]+)/$', views.ObtainAuthToken.as_view()),
url(r'^register/(?P<backend>[^/]+)/', views.register_by_access_token),
...

每次当我尝试做身份验证,OAuth.io工作和rqest到API返回

Everytime when I try to do auth, OAuth.io is working and the rqest to api returns

细节:无效的标记

我想我错过了的蟒蛇 - 社会 - 身份验证或我做的一切错误配置的东西。所以,我会很高兴,如果任何人有一些想法,并希望能帮助:)

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 :)

推荐答案

以下行添加到您的ObtainAuthToken类

Add the following line to your ObtainAuthToken class

authentication_classes = ()

和您的错误{细节:无效令牌}会自行消失。

and your error {"detail": "Invalid token"} will go away.

这里的原因...

您请求包含以下标题

Authorization: Token yourAccessToken

但你在DEFAULT_AUTHENTICATION_CLASSES定义rest_framework.authentication.TokenAuthentication。

yet you have defined rest_framework.authentication.TokenAuthentication in DEFAULT_AUTHENTICATION_CLASSES.

在此基础上的Django会认为你要为你传递一个令牌进行令牌认证,它失败了,因为这是为Facebook的访问令牌,并在你的Django * _token数据库,因此无效的令牌错误不存在。你的情况,你需要做的是告诉Django不使用TokenAuthentication该视图。

Based on this Django thinks you want to perform token authentication as you have passed a Token in. It fails because this is an access token for facebook and doesn't exist in your django *_token database, hence the invalid token error. In your case all you need to do is tell Django not to use TokenAuthentication for this view.

仅供参考

请您可能会遇到更多的错误作为你的code执行被执行ObtainAuthToken POST方法前停了下来。试图逐步执行code个人时,我得到了错误

Keep in mind you may encounter further errors as your code execution was halted before the post method of ObtainAuthToken executed. Personally when trying to step through your code I got the error

'DjangoStrategy' object has no attribute 'backend'

backend = request.strategy.backend

和通过更改

uri = ''
strategy = load_strategy(request)
backend = load_backend(strategy, backend, uri)

此外,你应该更新你register_by_access_token功能,因为它不与你所引用的博客工作code排队。博客作者这里公布了他的最新code 。您的版本不拉令牌,如果你想用它与第三方如Facebook要权威性这是需要在auth头的。

Additionally you should update your you register_by_access_token function as it doesn't line up with the working code from the blog you referenced. The blog author posted his latest code here. Your version doesn't pull the token out of the auth header which is required if you want to use it to auth with a third party like facebook.

这篇关于Facebook的身份验证与AngularJS和Django的REST框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆