Django and angular.js with authentication

I have a web application that is already written in Django and it works very well. I want to add some views for angular, as the plan is to move in that direction. One of the problems that I am facing is that some of my controllers require login, with django we usually use the @login_required decorator, and everything is fine.

But with angular.js calling the controllers (for api), redirection does not occur. I assume that I will have to somehow check if my django user is verified directly from the angular side. Are there any explanations on how to confirm this on angular? I struggled with this and read the following:

https://docs.angularjs.org/api/ng/service/ $ http

https://medium.com/@vince_prignano/angular-js-with-django-bde834dbd61e

$ routeProvider does not start after login redirection

http://www.django-rest-framework.org/api-guide/authentication/

Basically, I want to confirm through Angular that my user is logged in, and if not, redirect them to the login page.

EDIT

I implement an intercept request as shown here:

Interceptor not working

However, in django @login_required it returns the html of the redirect page. Is there a way to get the url and send the user there?

+6
source share
5 answers

When defining my application, I do this:

$httpProvider.interceptors.push('errorInterceptor');

and the code for this is below:

 app.factory('errorInterceptor', ['$q', '$rootScope', '$location', function ($q, $rootScope, $location) { return { request: function (config) { return config || $q.when(config); }, requestError: function(request){ return $q.reject(request); }, response: function (response) { return response || $q.when(response); }, responseError: function (response) { if (response && response.status == 302 && response.data.url) { window.location = response.data.url; return; } return $q.reject(response); } }; }]); 

Basically, we cannot use login_required . We need to create a new decorator and provide status 302 with a URL.

+1
source

Add the solution to your $ routeProvider as:

  $routeProvider .when('/', { templateUrl: '/views/main.html' }) .when('/admin', { templateUrl: 'views/admin.html', controller: 'AdminCtrl', resolve: { loggedin: checkLoggedin } }) .when('/login', { templateUrl: 'views/login.html', controller: 'LoginCtrl' }) .otherwise({ redirectTo: '/' }); - 

See more at: https://vickev.com/#!/article/authentication-in-single-page-applications-node-js-passportjs-angularjs

+1
source

As mentioned in the previous answer, it would be better if your Django server can give a 401 response when a login is required. Now it seems that it sends 302, which you can still see in the browser if you make an XHR request. As you have discovered, using $ http interceptors in Angular is the usual way of finding 401 and sending the user to the login page.

I took a different approach: we implement a service that abstracts this a bit using the $user.get() method - it makes a request to a known endpoint (in my case, /api/users/current ) and rejects the returned promise if it sees 401 In your case, you can implement a rejection handler that uses window.location.href to send the user to your special login page

Disclaimer: I work in Stormpath and we spent a time log thinking about it :) In my comments above Im referring to our Stormpath Angular SDK - you can look at this library to find out how Ive solved this problem.

+1
source

If you make API calls through AJAX back to the server, most likely you do not want the response redirected to the login page.

I have the same use case and I made my own decorator to return 403 when the user is not logged in. Instead, you can use 401 if you want (I left it commented out).

I use 403 because 401 seems to imply WWW authentication .

 from django.http import HttpResponse, HttpResponseForbidden def logged_in_or_deny(func): def check_request(request, *args, **kwargs): if (request.user.is_authenticated()): return func(request, *args, **kwargs) else: return HttpResponseForbidden('You must be logged in') # 403 Response #return HttpResponse('You must be logged in', status=401) # 401 Response return check_request 

Then you defend your opinion as follows:

 @logged_in_or_deny def your_view(request): # ... your code ... return HttpResponse('Your normal response :)') 

From Angular, it looks like you already know how to use an interceptor to check the response code and redirect the user accordingly. If you use 403 or 401, you should check against the response body in case you respond with similar errors in the future.

While what you already had will work, 302 answers may be used for other reasons. It is better to have an explicit 4xx response rather than a 3xx redirect response, as it will immediately become apparent that this is a client-side error (lack of authentication).

+1
source

You can use the Http-Auth-Interceptor. Suppose that you need to log in to view and the user makes a request to view without logging in, then @login_required decorator returns a response with a response code of 401. In auth interceptor it intercepts the status code if the status code is 401, then redirects the user to the page entrance.

example site: http://witoldsz.imtqy.com/angular-http-auth/

0
source

Source: https://habr.com/ru/post/983298/


All Articles