User Authentication in Django Rest Framework + Angular.js web app

PythonDjangoAngularjsAuthenticationDjango Rest-Framework

Python Problem Overview


I'm working on a webapp where users can login to see their online wine cellar.

I've got the Django REST models setup, as well as the front-end design in Angular but I'm having trouble putting the pieces together and my main issue is for user authentication.

I've read many posts on here and various tutorials but I can't seem to find a step by step method to implement authentication:

  • What kind of auth should be used (Token, Session, Other?)
  • How is authentication managed on the server side (is it a view? a method in the UserModel or UserManager?)
  • I have a custom User model (using email as username). Can I use the generic Django login method or do I need to create my own?
  • How is the authentication process managed between the server and client side?

From what I understand Angular makes a POST request on a url where DRF verifies that username and password match and returns a token or other auth proof.

I feel like I'm close but I need a more general view of how this works to put the pieces together.

Thanks in advance

Python Solutions


Solution 1 - Python

I imagine there are a lot of ways to do this, let me explain what I do, hopefully it is helpful. This is going to be a long post. I would love to hear how others do this, or better ways of implementing the same approach. You can also check out my seed project on Github, Angular-Django-Seed.

I use token authentication with Witold Szczerba's http-auth-interceptor. The beauty of his approach is that whenever a request is sent from your site without proper credentials, you are redirected to the login screen, but your request is queued to be re-fired on login complete.

Here is a login directive used with the login form. It posts to Django's auth token endpoint, sets a cookie with the response token, sets the default header with the token so all requests will be authenticated, and fires the http-auth-interceptor login event.

.directive('login', function ($http, $cookieStore, authService) {
return {
  restrict: 'A',
  link: function (scope, elem, attrs) {

    elem.bind('submit', function () {
      var user_data = {
            "username": scope.username,
            "password": scope.password,
      };

      $http.post(constants.serverAddress + "api-token-auth", user_data, {"Authorization": ""})
          .success(function(response) {
              $cookieStore.put('djangotoken', response.token);
              $http.defaults.headers.common['Authorization'] = 'Token ' + response.token;
              authService.loginConfirmed();
          });
    });
  }
}

})

I use the module .run method to set check for the cookie when a user comes to the site, if they have the cookie set I set the default authorization.

.run(function($rootScope) {
  $rootScope.$broadcast('event:initial-auth');
})

Here is my interceptor directive that handles the authService broadcasts. If login is required, I hide everything and show the login form. Otherwise hide the login form and show everything else.

.directive('authApplication', function ($cookieStore, $http) {
	return {
		restrict: 'A',
		link: function (scope, elem, attrs) {

          var login = elem.find('#login-holder');
          var main = elem.find('#main');

          scope.$on('event:auth-loginRequired', function () {
            main.hide();
            login.slideDown('fast');
  		  });

  		  scope.$on('event:auth-loginConfirmed', function () {
    		main.show();
    		login.slideUp('fast');
  		  });

          scope.$on('event:initial-auth', function () {
             if ($cookieStore.get('djangotoken')) {
               $http.defaults.headers.common['Authorization'] = 'Token ' + $cookieStore.get('djangotoken');
             }
             else {
               login.slideDown('fast');
               main.hide();
             }
          });
		}
     }
  })

To use it all my html was basically like this.

<body auth-application>
  <div id="login-holder">
    ... login form
  </div>

  <div id="main">
    ... ng-view, or the bulk of your html
  </div>

Solution 2 - Python

Check out django-rest-auth and angular-django-registration-auth also

https://github.com/Tivix/angular-django-registration-auth

https://github.com/Tivix/django-rest-auth

We've tried to solve most common Django auth/registration related things from a backend and angular perspective in these two libraries.

Thanks!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbpipatView Question on Stackoverflow
Solution 1 - PythonZack ArgyleView Answer on Stackoverflow
Solution 2 - PythonchachraView Answer on Stackoverflow