I am getting status code 403 when I try to log in after successfully being logged in and logged out.
Client side is written in Angular and server side is in Django.
This goes as follows:
- Client requests url
'/'
fetches main HTML template with all required static files ( angular, bootstrap, jQuery sources and angular sources defined by me) with<div ng-view></div>
tag into which further templates will be inserted. - Via $location service is redirected to url
'/#/login'
- This rule from
$routeProvider
is executed once'/#/login'
is hit:$routeProvider.when('/login', { templateUrl: 'login.html' });
'login.html'
is served by django view and form for logging in is rendered to the user- User logs in successfully providing proper credentials
- Then user logs out, by clicking on a button, which fires
'$http.get( '/logout/' );'
and then is redirected to url'/#/login'
- Here is the problem. When user fills in credential form and sends
'POST'
request, 403 is returned. I thought that it is, because this routing is done only by angular and since'login.html'
template has already been requested it has been catched and can be served without hitting backend, but after logging out currently possesed CSRF cookie is stale, so that's why I am getting 403. So I tried to remove that template:
logout: function(){
var forceLoginTemplateRequest = function(){
if( $templateCache.get('login.html') !== 'undefined'){
$templateCache.remove('login.html');
}
};
var responsePromise = $http.get(
urls.logout
);
responsePromise.success(forceLoginTemplateRequest);
return responsePromise;
}
After doing that I could see client side requesting 'login.html'
template always after logging out, so I thought I could provide CSRF cookie when serving that template from backend:
#urls.py
urlpatterns = patterns(
'',
...
url(r'^$', serve_home_template),
url(r'^login.html$', serve_login_template),
url(r'^login/', login_view, name='login'),
url(r'^logout/', logout_view, name='logout'),
...
)
#views.py
@ensure_csrf_cookie
def serve_login_template(request):
return render(request, "login.html")
@ensure_csrf_cookie
def serve_home_template(request):
return render(request, 'home.html')
But still it doesn't work and I am getting 403 when trying to log in after logging out. The only way I managed it to work is to simply refresh the page so that every single file, whether template or source file is requested again from the backend and CSRF cookie is updated with them.
Here is my app's run section for making sure CSRF cookie is sent with every request:
mainModule.run(['$http','$cookies', '$location', '$rootScope', 'AuthService', '$templateCache',
function($http, $cookies, $location, $rootScope, AuthService, $templateCache) {
$http.defaults.headers.common['X-CSRFToken'] = $cookies.csrftoken;
$rootScope.$on( "$routeChangeStart", function(event, next, current) {
if ( !(AuthService.isLoggedIn() == "true")){
$location.path('/login');
}
});
}]);
This could be a cache problem. Try to add the
never_cache
decorator to all your views: