Duncan Gichimu
Duncan Gichimu

Reputation: 466

Angular http request with Django Rest JWT

Sending a request to my django backend from angular returns a 401 unauthorized. Here is a http request on a logout function.

import { Injectable } from '@angular/core';
import { HttpClient,HttpHeaders } from '@angular/common/http';
import { RequestOptions } from '@angular/http';
import { authLoginUrl,authLogoutUrl }  from '../../../../config/endpoints';
import 'rxjs/add/operator/map';
import { AlertService } from '../../../../../core/services/alert.service';
@Injectable()
export class LoginService{
    public token: string;

    constructor(private http: HttpClient) {
        // set token if saved in local storage
        var currentUser = JSON.parse(localStorage.getItem('currentUser'));
        this.token = currentUser && currentUser.token;
    }

    logout(): void {
        // notify backend of user logout
        //authLogoutUrl = "http://127.0.0.1:8000/api/auth/logout/"
        this.http.post(authLogoutUrl,{
            headers: new HttpHeaders().set('Authorization', 'JWT ' + this.token)
            })
            .subscribe()           
    }
}  

However request is authorized when I send it through curl.

curl -X POST -H "Authorization: JWT <the_token>" http://localhost:8000/api/auth/logout/

The logout view is in my django backend:

class LogoutView(views.APIView):
    permission_classes = (permissions.IsAuthenticated,)

    def post(self, request, format=None):
        logout(request)

        return Response({}, status=status.HTTP_204_NO_CONTENT)

Everyting seems as though it is working alright. The preflight request returns 200, but the request itself is unauthorized. Here are the request headers

Request Headers

Cors settings django rest:

CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_HEADERS = (
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
)

#Rest Framework
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAuthenticated',),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),
    'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',),
    'DEFAULT_PAGINATION_CLASS':
    'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE':100,
}

Since it works with curl and the preflight request is approved, I can only assume the problem is with angular or cors.

1) Are the headers set correctly? 2) Is this a cors problem?

Upvotes: 1

Views: 1223

Answers (1)

Duncan Gichimu
Duncan Gichimu

Reputation: 466

The problem was that the header was not being set. I'm not sure why this was the case, but I solved this by creating a Http Interceptor. It intercepts http requests and adds the JWT token to the headers for each http request. This article goes over making an Interceptor really well.

https://theinfogrid.com/tech/developers/angular/building-http-interceptor-angular-5/

Here is the interceptor code as well.

import { Injectable, Injector } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';

import { Observable } from 'rxjs/Rx';
import 'rxjs/add/observable/throw'
import 'rxjs/add/operator/catch';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
    private token: string;
    constructor() { }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        this.getToken();

        console.log("intercepted request ... ");

        // Clone the request to add the new header.
        var authReq;
        if (this.token){
            authReq = req.clone({ headers: req.headers.set("Authorization", "JWT " + this.token)});
            console.log("Sending request with new header now ...");
        } else {
            authReq = req;
        }
        //send the newly created request
        return next.handle(authReq)
            .catch((error, caught) => {
            //intercept the respons error and displace it to the console
            console.log("Error Occurred");
            console.log(error);
            //return the error to the method that called it
            return Observable.throw(error);
        }) as any;
    }

    getToken() {
        let currentUser = JSON.parse(localStorage.getItem('currentUser'));
        this.token = currentUser && currentUser.token;
    }

Upvotes: 2

Related Questions