auth - Autenticación de Facebook con AngularJS y Django REST Framework
django rest framework facebook login (3)
Agregue la siguiente línea a su clase ObtainAuthToken
authentication_classes = ()
y su error {"detalle": "token inválido"} desaparecerá.
Este es el por qué...
Su solicitud contiene el siguiente encabezado
Authorization: Token yourAccessToken
sin embargo, ha definido rest_framework.authentication.TokenAuthentication en DEFAULT_AUTHENTICATION_CLASSES.
En función de esto, Django cree que desea realizar la autenticación de token cuando haya pasado un token. Falla porque este es un token de acceso para Facebook y no existe en su base de datos django * _token, de ahí el error del token no válido. En su caso, todo lo que necesita hacer es decirle a Django que no use TokenAuthentication para esta vista.
FYI
Tenga en cuenta que puede encontrar más errores ya que la ejecución del código se detuvo antes de que se ejecutara el método de publicación de ObtainAuthToken. Personalmente cuando trato de pasar por su código, recibí el error
''DjangoStrategy'' object has no attribute ''backend''
en
backend = request.strategy.backend
y lo resolvió cambiando a
uri = ''''
strategy = load_strategy(request)
backend = load_backend(strategy, backend, uri)
Además, debe actualizar su función register_by_access_token ya que no se alinea con el código de trabajo del blog al que hizo referencia. El autor del blog publicó su último código here . Su versión no extrae el token del encabezado de autenticación, que es obligatorio si desea usarlo para autenticarse con un tercero como Facebook.
Estoy desarrollando una aplicación SPA con AngularJS que utiliza el back-end de Django para el servidor. La forma en que me comunico con el servidor desde el SPA es con django-rest-framework . Así que ahora quiero hacer autenticación con Facebook (también en google y twitter) y leo mucho sobre este tema y encontré OAuth.io que está haciendo la autenticación en el lado SPA del cliente y python-social-auth que está haciendo lo mismo pero en el lado del servidor.
Por lo tanto, actualmente solo tengo la autenticación del cliente, mi aplicación se conecta a Facebook (con OAuth.io) y se registra con éxito. Este proceso está devolviendo access_token y luego estoy haciendo una solicitud a mi API que tiene que iniciar sesión en este usuario o crear una cuenta para este usuario con un token dado y esta parte no está funcionando. Así que no estoy seguro de dónde estoy equivocado, tal vez porque no hay un tutorial completo sobre el uso de Python-social-auth, así que tal vez me esté perdiendo algo o ... No sé ...
Entonces algún código de esto es lo que tengo:
En el lado de SPA: Esta es la conexión con OAuth.io y está funcionando porque recibo el token de acceso. Entonces tengo que hacer una solicitud a mi API de descanso. backend es ''facebook'', ''google'' o ''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'');
});
});
En el servidor de mi settings.py he agregado el complemento social a las aplicaciones instaladas, los preprocesadores de contexto de la plantilla, algunos back-end de autenticación y ese es mi archivo:
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'',
)
En mi views.py de la API tengo lo siguiente (lo encontré 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
Y finalmente tengo estas rutas en 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),
...
Cada vez que intento hacer auth, OAuth.io está funcionando y regresa el rqest to api
detalle: "token inválido"
Creo que me perdí algo en la configuración de python-social-auth o estoy haciendo todo mal. Así que me alegrará si alguien tiene algunas ideas y quiere ayudar :)
Estoy usando herramientas como tú, pero proporciono mi login / register / .... con el paquete django-allauth
, y luego uso django-rest-auth
para el manejo de la API.
Solo necesita seguir las instrucciones de instalación y luego usarlas para sus API de descanso.
Agregar allauth
y rest-auth
a su INSTALLED_APPS:
INSTALLED_APPS = (
...,
''rest_framework'',
''rest_framework.authtoken'',
''rest_auth''
...,
''allauth'',
''allauth.account'',
''rest_auth.registration'',
...,
''allauth.socialaccount'',
''allauth.socialaccount.providers.facebook'',
)
A continuación, agregue sus URL personalizados:
urlpatterns = patterns('''',
...,
(r''^auth/'', include(''rest_auth.urls'')),
(r''^auth/registration/'', include(''rest_auth.registration.urls''))
)
Finalmente, agregue esta línea:
TEMPLATE_CONTEXT_PROCESSORS = (
...,
''allauth.account.context_processors.account'',
''allauth.socialaccount.context_processors.socialaccount'',
...
)
Estos dos paquetes funcionan como un amuleto, y no necesita preocuparse por ningún tipo de registro de inicio de sesión, porque el paquete allauth
maneja el inicio de sesión del modelo django y el inicio de sesión de oAuth.
Espero que ayude
Sí. Resuelto La configuración no es correcta y debe agregar permisos.
REST_FRAMEWORK = {
# Use hyperlinked styles by default.
# Only used if the `serializer_class` attribute is not set on a view.
''DEFAULT_MODEL_SERIALIZER_CLASS'':
''rest_framework.serializers.HyperlinkedModelSerializer'',
# Use Django''s standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
''DEFAULT_PERMISSION_CLASSES'': [
''rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly''
]
}
y alguna información sobre la tubería:
SOCIAL_AUTH_PIPELINE = (
''social.pipeline.social_auth.social_details'',
''social.pipeline.social_auth.social_uid'',
''social.pipeline.social_auth.auth_allowed'',
''social.pipeline.social_auth.social_user'',
''social.pipeline.user.get_username'',
''social.pipeline.social_auth.associate_by_email'',
''social.pipeline.user.create_user'',
''social.pipeline.social_auth.associate_user'',
''social.pipeline.social_auth.load_extra_data'',
''social.pipeline.user.user_details''
)