Saltar al contenido

¿Cómo puedo usar Django OAuth Toolkit con Python Social Auth?

Si encuentras alguna incompatibilidad en tu código o trabajo, recuerda probar siempre en un ambiente de testing antes subir el código al proyecto final.

Solución:

Gran parte de la dificultad para implementar OAuth se reduce a comprender cómo se supone que funciona el flujo de autorización. Esto se debe principalmente a que este es el “punto de partida” para iniciar sesión, y cuando trabaja con un backend de terceros (utilizando algo como Python Social Auth), en realidad está haciendo esto dos veces: una vez para su API y una vez para la API de terceros.

Autorizar solicitudes usando su API y un backend de terceros

El proceso de autenticación que necesita es pasar por:

Diagrama de secuencia para la opción A

Mobile App -> Your API : Authorization redirect
Your API -> Django Login : Displays login page
Django Login -> Facebook : User signs in
Facebook -> Django Login : User authorizes your API
Django Login -> Your API : User signs in
Your API -> Mobile App : User authorizes mobile app

Estoy usando “Facebook” como backend de terceros aquí, pero el proceso es el mismo para cualquier backend.

Desde la perspectiva de su aplicación móvil, solo está redirigiendo a la /authorize URL proporcionada por Django OAuth Toolkit. A partir de ahí, la aplicación móvil espera hasta que se alcanza la URL de devolución de llamada, al igual que en el flujo de autorización estándar de OAuth. Casi todo lo demás (inicio de sesión de Django, inicio de sesión social, etc.) lo maneja Django OAuth Toolkit o Python Social Auth en segundo plano.

Esto también será compatible con prácticamente cualquier biblioteca OAuth que use, y el flujo de autorización funcionará de la misma manera sin importar qué backend de terceros se use. Incluso manejará el caso (común) en el que necesita poder admitir el backend de autenticación de Django (correo electrónico / nombre de usuario y contraseña), así como un inicio de sesión de terceros.

Opción A sin un backend de terceros

Mobile App -> Your API : Authorization redirect
Your API -> Django Login : Displays login page
Django Login -> Your API : User signs in
Your API -> Mobile App : User authorizes mobile app

Lo que también es importante tener en cuenta aquí es que la aplicación móvil (que podría ser cualquier cliente OAuth) nunca recibe los tokens OAuth de Facebook / terceros. Esto es increíblemente importante, ya que se asegura de que su API actúe como intermediario entre el cliente OAuth y las cuentas sociales de su usuario.

Diagrama de secuencia con su API como guardián

Mobile App -> Your API : Authorization redirect
Your API -> Mobile App : Receives OAuth token
Mobile App -> Your API : Requests the display name
Your API -> Facebook : Requests the full name
Facebook -> Your API : Sends back the full name
Your API -> Mobile App : Send back a display name

De lo contrario, el cliente de OAuth podría omitir su API y realizar solicitudes en su nombre a las API de terceros.

Diagrama de secuencia para omitir su API

Mobile App -> Your API : Authorization redirect
Your API -> Mobile App : Receives Facebook token
Mobile App -> Facebook : Requests all of the followers
Facebook -> Mobile App : Sends any requested data

Notarás que en este punto habría perdido todo el control sobre los tokens de terceros. Esto es especialmente peligroso porque la mayoría de los tokens pueden acceder a una amplia gama de datos, lo que abre la puerta al abuso y, finalmente, se cae. bajo tu nombre. Lo más probable es que aquellos que inician sesión en su API / sitio web no tenían la intención de compartir su información social con el cliente OAuth y, en cambio, esperaban que usted mantuviera esa información privada (tanto como fuera posible), pero en cambio, está exponiendo esa información a todos.

Autenticar solicitudes a su API

Cuando la aplicación móvil usa tu token de OAuth para hacer solicitudes a tu API, toda la autenticación se realiza a través de Django OAuth Toolkit (o su proveedor de OAuth) en segundo plano. Todo lo que ves es que hay un User asociado con su solicitud.

Cómo se validan los tokens de OAuth

Mobile App -> Your API : Sends request with OAuth token
Your API -> Django OAuth Toolkit : Verifies the token
Django OAuth Toolkit -> Your API : Returns the user who is authenticated
Your API -> Mobile App : Sends requested data back

Esto es importante porque después de la etapa de autorización, no debería haber ninguna diferencia si el usuario proviene de Facebook o del sistema de autenticación de Django. Tu API solo necesita un User para trabajar, y su proveedor de OAuth debería poder manejar la autenticación y verificación del token.

Esto no es muy diferente de cómo el marco REST de Django autentica al usuario cuando se usa la autenticación respaldada por sesión.

Diagrama de secuencia para la autenticación mediante sesiones

Web Browser -> Your API : Sends session cookie
Your API -> Django : Verifies session token
Django -> Your API : Returns session data
Your API -> Django : Verifies the user session
Django -> Your API : Returns the logged in user
Your API -> Web Browser : Returns the requested data

De nuevo, todo esto es manejado por Django OAuth Toolkit y no requiere trabajo adicional para implementar.

Trabajar con un SDK nativo

En la mayoría de los casos, autenticará al usuario a través de su propio sitio web y usará Python Social Auth para manejar todo. Pero la única excepción notable es cuando se usa un SDK nativo, como la autenticación y autorización se maneja a través del sistema nativo, lo que significa estás omitiendo tu API por completo. Esto es ideal para aplicaciones que necesitan iniciar sesión con un tercero o aplicaciones que no usan su API en absoluto, pero es una pesadilla cuando ambos se juntan.

Esto es porque su servidor no puede validar el inicio de sesión y se ve obligado a asumir que el inicio de sesión es válido y genuino, lo que significa que pasa por alto toda la seguridad que Python Social Auth le brinda.

El uso de un SDK nativo puede causar problemas

Mobile App -> Facebook SDK : Opens the authorization prompt
Facebook SDK -> Mobile App : Gets the Facebook token
Mobile App -> Your API : Sends the Facebook token for authorization
Your API -> Django Login : Tries to validate the token
Django Login -> Your API : Returns a matching user
Your API -> Mobile App : Sends back an OAuth token for the user

Notará que esto omite su API durante la fase de autenticación y luego obliga a su API a hacer suposiciones sobre el token que se pasa. Pero definitivamente hay casos en los que este riesgo puede valer la pena, por lo que debe evaluarlo antes de desecharlo. Es un intercambio entre inicios de sesión rápidos y nativos para su usuario y potencialmente manejando tokens malos o maliciosos.

Lo resolví usando tu opción A.

Lo que hago es registrar usuarios que utilizan un tercero para registrarse mediante su token de acceso de terceros.

url(r'^register-by-token/(?P[^/]+)/$',
    views.register_by_access_token),

De esta manera, puedo emitir una solicitud GET como esta:

GET http://localhost:8000/register-by-token/facebook/?access_token=123456

Y register_by_access_token se llama. request.backend.do_auth consultará al proveedor la información del usuario del token y registrará mágicamente una cuenta de usuario con la información o iniciará sesión con el usuario si ya está registrado.

Luego, creo un token manualmente y lo devuelvo como JSON para permitir que el cliente consulte mi API.

from oauthlib.common import generate_token
...
@psa('social:complete')
def register_by_access_token(request, backend):
    # This view expects an access_token GET parameter, if it's needed,
    # request.backend and request.strategy will be loaded with the current
    # backend and strategy.
    third_party_token = request.GET.get('access_token')
    user = request.backend.do_auth(third_party_token)

    if user:
        login(request, user)

        # We get our app!   
        app = Application.objects.get(name="myapp")

        # We delete the old token
        try:
            old = AccessToken.objects.get(user=user, application=app)
        except:
            pass
        else:
            old.delete()

        # We create a new one
        my_token = generate_token()

        # We create the access token 
        # (we could create a refresh token too the same way) 
        AccessToken.objects.create(user=user,
                                   application=app,
                                   expires=now() + timedelta(days=365),
                                   token=my_token)

        return "OK" # you can return your token as JSON here

    else:
        return "ERROR"

Simplemente no estoy seguro de la forma en que genero el token, ¿es una buena práctica? Bueno, mientras tanto, ¡funciona!

Quizás django-rest-framework-social-oauth2 es lo que estás buscando. Este paquete depende de python-social-auth y django-oauth-toolkit, que ya usas. Escaneé rápidamente la documentación y parece implementar exactamente lo que está tratando de hacer.

Si eres capaz, puedes dejar un escrito acerca de qué te ha parecido este ensayo.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *