Issue
In Django, when the CSRF_COOKIE_HTTPONLY
setting is set to True, the CSRF cookie gains the httponly flag, which is desirable from a security perspective, but breaks the standard angular solution of adding this cookie to the httpProvider like so:
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
Through Django 1.9, there was a workaround where you could just pass the cookie directly to the app by putting this in the template:
<script>
window.csrf_token = "{{ csrf_token }}";
</script>
And putting this in the angular app:
angularApp.config(["$httpProvider", function($httpProvider) {
$httpProvider.defaults.headers.common["X-CSRFToken"] = window.csrf_token;
}]
Unfortunately, this doesn't work for single page angular apps in Django 1.10+ since the CSRF cookie changes after every request. How do you make post requests from Angular to Django 1.10+ with the CSRF_COOKIE_HTTPONLY
setting on?
NB: Disabling CSRF protection is not an acceptable answer.
Solution
Django has a documented solution for this. Any Javascript can get the CSRF token from the DOM even if CSRF_COOKIE_HTTPONLY is enabled as long as the CSRF token is in the DOM.
Step 1: I add a tag to let Django middleware put csrf token to the DOM
# Django put CSRF token to DOM
{% csrf_token %}
Step 2: Implement an HttpInterceptor to get csrf from DOM
import { Injectable } from '@angular/core';
import { HttpEvent, HttpRequest, HttpHandler, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class DjangoCSRFInterceptor implements HttpInterceptor {
intercept(httpRequest: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const token = (
document.querySelector('[name=csrfmiddlewaretoken]') as HTMLInputElement
).value;
return httpRequest.clone({ headers: httpRequest.headers.set('X-CSRFToken, token) });
}
}
Step 3: Put HttpInterceptor to your Angular module providers
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: DjangoCSRFInterceptor, multi: true }
]
Answered By - Chanh Ha
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.