3

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?

DaveIdito
  • 1,546
  • 14
  • 31

2 Answers2

3

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)

omab
  • 3,721
  • 19
  • 23
  • Hmm, there's no setting with the name `LOGIN_REDIRECT_URL`, therefore the path is never hit. – DaveIdito May 14 '21 at 14:32
  • You can define the setting yourself with the desired value – omab May 14 '21 at 14:37
  • I tried, but I am still clueless. I was thinking there would be some final `redirect` function in the strategy which I can override. Do you have any further pointers? – DaveIdito May 14 '21 at 14:50
  • The redirect is handled by the common [`do_complete()` action](https://github.com/python-social-auth/social-core/blob/eeee9763862d768627e134a42e4664456b6eabec/social_core/actions.py#L58-L90), do you happen to have `NEW_ASSOCIATION_REDIRECT_URL` or `NEW_USER_REDIRECT_URL` settings defined? – omab May 14 '21 at 14:55
  • Thanks a lot! No, I have none of those defined. – DaveIdito May 14 '21 at 14:57
  • Still can't get it to work. Sadly the only option I have left is to turn `rest_framework.authentication.SessionAuthentication` back on :/ – DaveIdito May 14 '21 at 15:52
  • Could you try to debug that section I've linked (on `do_complete()`)? It will give point you on what condition your user is landing on and from there you can infer the setting used to pull the redirect value. – omab May 14 '21 at 16:32
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/232422/discussion-between-daveidito-and-omab). – DaveIdito May 14 '21 at 16:46
0

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.

DaveIdito
  • 1,546
  • 14
  • 31