Я разрабатываю приложение SPA с AngularJS, в котором используется Django для сервера. Способ, которым я общаюсь с сервером из SPA, - django-rest-framework. Итак, теперь я хочу сделать аутентификацию с помощью facebook (google и twitter тоже), и я много читал по этой теме и нашел OAuth.io, который делает на стороне клиента SPA и python-social-auth, который делает то же самое, но на стороне сервера.
Итак, в настоящее время у меня есть только клиентское приложение, мое приложение подключается к facebook (с OAuth.io) и успешно зарегистрируется. Этот процесс возвращает access_token, а затем я делаю запрос к моему API, который должен войти в этот пользователь или создать учетную запись для этого пользователя, указав токен, и эта часть не работает. Поэтому я не уверен, где я ошибаюсь, может быть, потому, что нет полного руководства по использованию python-social-auth, поэтому, возможно, я чего-то не хватает или не знаю..
Итак, некоторый код этого, что у меня есть:
На стороне SPA: Это соединение с OAuth.io и работает, потому что я получаю токен доступа. Затем я должен сделать запрос на мой API для отдыха. backend - это "facebook", "google" или "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 я добавил социальный плагин к установленным приложениям, препроцессорам контекста шаблона, некоторым резервным серверам и это мой файл:
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',
)
В моем view.py API у меня есть следующее (я нашел здесь):
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:
...
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),
...
Каждый раз, когда я пытаюсь выполнить auth, OAuth.io работает, а rqest to api возвращает
подробнее: "Недопустимый токен"
Я думаю, что я пропустил что-то в конфигурации python-social-auth, или я делаю все неправильно. Поэтому я буду рад, если у кого есть какие-то идеи и вы хотите помочь:)