60
votes

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

2
I understand the question is very broad but I am not looking for actual code, rather a methodology for implementing a simple login in DRF. With a few quality answers like @zack-argyle this could be of great help for novice DRF developpersbpipat
That this question was closed as too broad is evidence of the pernicious rot of the SO community. This question was asked fairly concisely, answered well by Zack, and the first result when searching for the exact problem on google. It's a question that can't be solved by RTFM so it gets closed by power-drunk mods. Now, because it is closed, more quality answers can't be provided. If you voted to close this, please promptly go to Tiajuana and take up a life as a performer in a variety show.Ted

2 Answers

49
votes

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>
16
votes

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!