1

I'm in the process of building a Vue SPA that will use the standard Django Session Authentication since the Django app and the Vue app will be on the same server and same domain.

I've always used django-allauth for everything authentication-related, but the problem, in this case, is that authentication is not handled by Django templates, but I use AJAX to send POST requests to Django to register, sign in, and everything else.

Is there any way to make Django-Allauth or Django send JSON responses instead of standard HTML and redirects?

Here is an example POST request from my code that i use to login:

bodyFormData.append('csrfmiddlewaretoken', this.csrf_token)
bodyFormData.append('login', 'root');
bodyFormData.append('password', 'Stest');

axios({
  method: "post",
  url: "http://127.0.0.1:8000/accounts/login/",
  data: bodyFormData,
  withCredentials: true,
  headers: {"Content-Type": "application/json"},
})
.then(function (response) {
  //handle success
})
.catch(function (response) {
  //handle error
});

And here is the login view:

class LoginView(
    RedirectAuthenticatedUserMixin, AjaxCapableProcessFormViewMixin, FormView
):
    form_class = LoginForm
    template_name = "account/login." + app_settings.TEMPLATE_EXTENSION
    success_url = None
    redirect_field_name = "next"

    @sensitive_post_parameters_m
    def dispatch(self, request, *args, **kwargs):
        return super(LoginView, self).dispatch(request, *args, **kwargs)

    def get_form_kwargs(self):
        kwargs = super(LoginView, self).get_form_kwargs()
        kwargs["request"] = self.request
        return kwargs

    def get_form_class(self):
        return get_form_class(app_settings.FORMS, "login", self.form_class)

    def form_valid(self, form):
        success_url = self.get_success_url()
        try:
            return form.login(self.request, redirect_url=success_url)
        except ImmediateHttpResponse as e:
            return e.response

    def get_success_url(self):
        # Explicitly passed ?next= URL takes precedence
        ret = (
            get_next_redirect_url(self.request, self.redirect_field_name)
            or self.success_url
        )
        return ret

    def get_context_data(self, **kwargs):
        ret = super(LoginView, self).get_context_data(**kwargs)
        signup_url = passthrough_next_redirect_url(
            self.request, reverse("account_signup"), self.redirect_field_name
        )
        redirect_field_value = get_request_param(self.request, self.redirect_field_name)
        site = get_current_site(self.request)

        ret.update(
            {
                "signup_url": signup_url,
                "site": site,
                "redirect_field_name": self.redirect_field_name,
                "redirect_field_value": redirect_field_value,
            }
        )
        return ret

This seems to work fine, it logs me in but the response is HTML and from the network tabs I can see that Django tries to redirect me to another page (because that's what it does when authentication is handled by Django templates).

Is there any way I can make it send only JSON responses? Do I have to override some view or am I forced to change the code of the library? Any advice is appreciated

Jack022
  • 867
  • 6
  • 30
  • 91

2 Answers2

1

I briefly looked through the code of django-allauth. I see one opportunity that may put you in the right direction?

django-allauth allows you to set your own adapter.

For example if you have an app called "my_applabel" and place a file custom_adapter.py with the following class and inherit the DefaultAccountAdapter:

class MyOwnAdapter(DefaultAccountAdapter):
    def ajax_response(self, request, response, redirect_to=None, form=None, data=None):
        # Craft your own response.

in settings try ACCOUNT_ADAPTER = 'my_applabel.custom_adapter.MyOwnAdapter'

see docs ACCOUNT_ADAPTER

It gives opportunity to override certain behaviours/methods from the DefaultAccountAdapter.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Daniel Backman
  • 5,121
  • 1
  • 32
  • 37
-1

You can use drf with djoser for it. It will give you to work with as usual token and also with jwt tokens for authorization, i think it will more better than using django template such way

Murad
  • 29
  • 1
  • Thank you, but in this case i want to use Session Authentication, with JWT tokens i would have problems with security such as where to store the token – Jack022 Mar 29 '21 at 09:30