Angular 2 Login to Django Rest Framework Backend

dd_123 picture dd_123 · Dec 14, 2016 · Viewed 7.9k times · Source

I am using Angular 2 as my front-end and Django Rest Framework on the backend to build a webapp.

I have set up a basic Angular 2 app that pulls data from my Django Rest Framework backend. The Django Rest Framework backend has the 'api-auth' url configured for logging in with the browsable API (see here for what I mean), but I am now running into trouble trying to log in from my Angular 2 app.

From what I can tell the best practice is to use JSON Web Tokens (JWT).

I have looked at almost all readily available tutorials/blog posts online but cannot seem to find a clear answer that sums up what I need to do on the backend (Django) and frontent (Angular 2). Anyone able to explain at a high level how to login to a Django Rest Framework backend from an Angular 2 front-end?

I'm specifically thinking about a "login" function that would sit in an ".service.ts" file in the Angular 2 app that would make a post request to some url ".../login". See the login() function in this blog to get a sense for what I mean. I was going off that example but it's not giving me the full picture of how to create the connection between the frontend & backend.

Answer

egeogretmen picture egeogretmen · Dec 18, 2016

This solution is for authentication using JWT, however there are also other solutions that don't use JWT.

This package(django-rest-framework-jwt) allows you to have auth endpoints to manage JWT in Django Rest Framework. You will have no problems if you follow the docs.

On the Angular2 end, you should have a login service that would request the JWT from the server by using the login credentials. That depends on your User Model in Django.

This blog post is very helpful with Angular2 JWT Authentication. You can check the login function in the authentication.service. I changed the code a bit to better suit the DRF-jwt.

let headers = new Headers({
  'Accept': 'application/json',
  'Content-Type': 'application/json',
});
let options = new RequestOptions({
  headers: headers
});
this.http.post(basePath + '/api-token-auth/', JSON.stringify({ username: username, password: password }), options)
.map((response: Response) => {
      // login successful if there's a jwt token in the response
      let token = response.json() && response.json().token;

      if (token) {
        // set token property
        this.token = token;

        // store username and jwt token in local storage to keep user logged in between page refreshes
        localStorage.setItem('id_token', token);

        // return true to indicate successful login
        return true;
      } else {
        // return false to indicate failed login
        return false;
      }
    });
// 'api-token-auth/' is the default endpoint with drf-jwt

This asks for the jwt from drf and stores it in localStorage.

From there on, all of your http requests that require authentication should include the Authorization header. There is an http wrapper that allows you to do this.

You can override the default configuration settings. The minimum configuration you need to override is that you should set is the globalHeaders. You don't need to change the tokenName or tokenGetter. Just add Content-Type: application/json and Accept: application/json. (DRF will check the Accept header to decide what kind of Renderer it should use.) You may also want to change the headerPrefix to JWT because drf-jwt uses that prefix for authorization header or you can change that from drf-jwt's settings.