Get DRF token from python-social-auth backend

Viewed 695

I am trying to integrate Social Authentication in my DRF backend. I decided to go with python-social-auth. If I serve my social login through Django (and an HTML view), I can see my login in successful. I also figured that I can redirect after successful social authentication as outlined here.

Until now, my frontend (a Nuxt app) was using DRF tokens. Even though:

  1. I can create valid tokens for social accounts.
  2. My frontend can redirect the users to -> complete authorization with OAuth sites e.g. Google, Twitter -> return back to the frontend.

Is it possible for me to somehow manage to redirect a successfully authenticated user to the frontend with the associated and valid DRF token as a query parameter?

2 Answers

You can, it's not trivial, tho. It's possible because the mechanism to retrieve URLs (success or errors ones) is delegated to strategies setting() method, which in the end invokes get_setting() on final implementations. This method you can override to add your custom logic.

These steps should get you on the road:

  1. Define a custom strategy

    from social_django.strategy import DjangoStrategy
    
    
    class CustomStrategy(DjangoStrategy):
        def get_setting(self, name):
            if name == 'LOGIN_REDIRECT_URL':
                token = get_drf_token()
                return f'/?toke={token}'
             else:
                 return super().get_setting(name)
    
  2. Point your SOCIAL_AUTH_STRATEGY settings to this new strategy (import path syntax)

Besides using a custom strategy, which I believe is more the library's style, there is another explicit solution:

Since python-social-auth allows redirection after successful authentication, open another endpoint that will a. generate a token b. redirect to the frontend. So I defined follow api_view:

@api_view(http_method_names=['get'])
def user_token(request):
    if request.user.is_authenticated:
        token, e = Token.objects.get_or_create(user=request.user)
        return redirect('<front-end>/?token='+token.key)
    else:
        return redirect(`<front-end>/login/?error=true')

Now a potential authentication flow is like this:

User visits front-end -> Click 'login using Github et.al.' -> Login at the third party (say, Github) -> Back to backend /success/ -> redirect to front-end url (based on the above view) with the token -> Handle the query parameter on the frontend (which is pretty trivial in my case where I am using Nuxt).

If we mount user_token at path /success/token/, then once the user visits: http:<backend>:/login/github/?next=/success/token/, every right step on users part will take him/her to the front-end with the query param token set as the right token.

UPDATE: This will only work if DRF has session authentication active, otherwise request.user.is_authenticated can never be true.

Related