Plug in django-allauth as endpoint in django-rest-framework

Each Answer to this Q is separated by one/two green lines.

I’m using django-allauth on my website for social logins. I also have a REST API powered by django-rest-framework that serves as the backend of a mobile app. Is there a way I can directly plug in allauth’s authentication backend to the REST api so that I can validate (and register) users who use Facebook login in the mobile app?

To clarify: The Facebook login part is handled by native SDKs. I need an endpoint that works like POST /user (that is, creates a new user), but takes Facebook oauth token as input instead of email/password etc.

You can use Django Rest Auth for this which depends on django-allauth. It’s very easy to integrate.

You can use this libray for social authentication django-rest-framework-social-oauth2. Try this django-allauth related code

urls.py

urlpatterns = [
    url(
        r'^rest/facebook-login/$',
        csrf_exempt(RestFacebookLogin.as_view()),
        name="rest-facebook-login"
    ),
]

serializers.py

class EverybodyCanAuthentication(SessionAuthentication):
    def authenticate(self, request):
        return None

views.py

class RestFacebookLogin(APIView):
    """
    Login or register a user based on an authentication token coming
    from Facebook.
    Returns user data including session id.
    """

    # this is a public api!!!
    permission_classes = (AllowAny,)
    authentication_classes = (EverybodyCanAuthentication,)

    def dispatch(self, *args, **kwargs):
        return super(RestFacebookLogin, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        try:
            original_request = request._request
            auth_token = request.GET.get('auth_token', '')

            # Find the token matching the passed Auth token
            app = SocialApp.objects.get(provider="facebook")
            fb_auth_token = SocialToken(app=app, token=auth_token)

            # check token against facebook
            login = fb_complete_login(original_request, app, fb_auth_token)
            login.token = fb_auth_token
            login.state = SocialLogin.state_from_request(original_request)

            # add or update the user into users table
            complete_social_login(original_request, login)
            # Create or fetch the session id for this user
            token, _ = Token.objects.get_or_create(user=original_request.user)
            # if we get here we've succeeded
            data = {
                'username': original_request.user.username,
                'objectId': original_request.user.pk,
                'firstName': original_request.user.first_name,
                'lastName': original_request.user.last_name,
                'sessionToken': token.key,
                'email': original_request.user.email,
            }
            return Response(
                status=200,
                data=data
            )

        except:
            return Response(status=401, data={
                'detail': 'Bad Access Token',
            })

While I’m not quite sure how to use allauth and rest-fremework together, allauth does not offer such an endpoint.

Suggestion: make your own that does a variation of the following:
Call allauth.socialaccount.providers.facebook.views.fb_complete_login(None, socialtoken) where socialtoken is as created in login_by_token. That performs (a few functions deeper) a django.contrib.auth.login, possibly creating the acct.

After that, for use on mobile devices, it might be possible to the the auth (not FB) token: get the user data (from session?), and call rest_framework.authtoken.views.obtain_auth_token

Notes:
1. This offers no way to resolve email conflicts or connect social/local accts.
2. I haven’t tried it – please post code if you can get it working.

You could use djoser but I don’t know how it cooperates with allauth:
https://github.com/sunscrapers/djoser


The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .