I am using ajax request to send POST but it got response 403 because of csrf_token. I divide the frontend just using Vuejs and backend using Django to just reponse API only so I can't use Django template to render {% csrf_token %} or having csrftoken in session to use getcookie('csrftoken') like in Django's doc recommend. Is there anybody face this problem like me and got some solutions ? So thank you if you can help me this.
You can set the CSRF token in the header of your AJAX request. E.g., if you use jquery and jquery.cookie library, you can easily retrieve the Django-set csrftoken cookie like so:
$.ajax({
url : 'YOUR_URL_HERE',
headers: {'X-CSRFToken': $.cookie('csrftoken')},
type: 'POST',
dataType: 'json',
data: {},
success: function() {
},
error: function(xhr, errMsg, err) {
},
});
Django documentation also includes a section on this: https://docs.djangoproject.com/en/1.11/ref/csrf/#ajax
Please note that this solution may depend on your specific Django settings. The Django documentation link above details everything pretty clearly.
EDIT:
Given that even your initial page request is not served by Django, here is how you can accomplish what you're looking for...
1.) Create a view in your Django app that manually generates and returns a CSRF token (using django.middleware.csrf.get_token):
def get_csrf_token(request):
token = django.middleware.csrf.get_token(request)
return JsonResponse({'token': token})
2.) You would also need to add an appropriate entry in your Django URLs file:
url(r'^get-token/$', get_csrf_token)
3.) Then your Vue.js app can fetch the CSRF token using this endpoint. This doesn't need to be a user-initiated event; for example, you can configure your front-end app to fetch it on the $(document).ready() event. Then, using your preferred AJAX library (I am using jQuery in my example):
$.ajax({
url: '/get-token/',
type: 'GET',
dataType: 'json',
success: function(data) {
$.cookie('csrftoken', data.token); // set the csrftoken cookie
}
});
4.) Now your csrftoken cookie is set and should be usable for subsequent POST requests.
$.ajax({
url : 'YOUR_URL_HERE',
headers: {'X-CSRFToken': $.cookie('csrftoken')},
type: 'POST',
dataType: 'json',
data: {},
success: function() {
},
error: function(xhr, errMsg, err) {
},
});
I have used jQuery for AJAX functionality and the jQuery.cookie library for getting and setting cookies, but of course you can use whichever library you would prefer for these functions.
According to the Django documentation you can simply use the ensure_csrf_cookie decorator on a view and that will send the cookie with the token with the response.
This is going to be wildly unpopular, but I've found it to be a relatively simple, secure and unobtrusive way to separate the front/backend.
In your VueJS app, you've probably got a login redirect when the user tries to access a page and are unauthenticated.
So instead of sending it to a vue router page, redirect it to /account/login/ (or some django app route - put an exception in cloudfront, or nginx proxy for /account/login/ to proxy pass to django) - then in the login.html template, just use a javascript window.location.href to your vueJS login page /login
The csrf_token will be set as a HttpOnly, secure cookie (which is what you want), and the disruption to the user is so minimal as to not even justify worrying about.
Related
I have a flask app and I want to send a request with Ajax from my page to another website on the internet( http://hihihi.com/v1/user_likes...for example and this App not flask and I can't change or add any code in the hihihi App).
I set a cookie in my Ajax requests but blocked by the browser. how can I fix this?
Back end flask:
#app.route('/tr')
def test():
return render_template('tr.html')
And in tr.html file as shown as I set header Ajax:
$.ajax({
url: 'http://hihihi.com/api',
type: 'POST',
contentType: 'application/json',headers:{'Cookie' : 'sdfsdfsdfsfdszfvgzzf'}
datatype: 'json',
})
.done(function(data) {
.
.
.
Refused to set unsafe header "Cookie" Error:
In addition, I use this link but not work for me.
Since you are making a same origin request all you need to do is set document.cookie before you make the request.
I'm building a separated VueJS/Django app where Django will communicate with the Vue frontend using JSON. In order to be able to use the standard session authentication and django-allauth i will deploy the two apps on the same server and on the same port.
Here is my problem: after i log in from the Vue app using Axios, i don't receive any response but i notice that a session is created on the db, so i'm assuming that i'm getting logged in. But if i try to reach and endpoint that prints request.user.is_authenticatedi get False, and request.user returns Anonymous, so i'm not logged in anymore. How can i solve this?
Here is my Axios code:
bodyFormData.append('login', 'root');
bodyFormData.append('password', 'test');
axios({
method: "post",
url: "http://127.0.0.1:8000/accounts/login/",
data: bodyFormData,
withCredentials: true,
headers: { "Content-Type": "application/json" },
})
.then(function (response) {
//handle success
console.log(response);
})
.catch(function (response) {
//handle error
console.log(response);
});
I think Django-Allauth supports AJAX authentication on its urls, but i don't understand how to make it return something and how can my Vue app stay authenticated once i submit the Axios form. Any advice is welcome!
I've been trying to make a POST to my Django application via XHTTP Request and jQuery with no correct result at all.
The fact is that the Django app is on one of my subdomains, and the web app is in another, not being part of the Django app, just only a separated app.
I've been reading the docs, but none of this works.
All of my subdomains are in the ALLOWED HOSTS list and in the CORS ORIGIN WHITELIST, and the petition works correctly with GET, but POST returns me a Forbidden 403 error telling CSRF Cookie not found.
This is the code of my petition.
var petition = new XMLHttpRequest();
petition.open('POST','http://localhost:8000/login/',true);
petition.setRequestHeader("X-CSRFToken",sessionStorage["csrf_token"]);
petition.send()
I already have stored the CSRF cookie in the session storage with this function.
function storeCSRFToken(){
var token;
$.ajax({
url : 'http://localhost:8000/token',
type: "GET",
dataType : "json",
success: function( data ){
token = data.csrf_token;
sessionStorage['csrf_token'] = token;
}
});
}
Any clue of what is going wrong?
I followed the doc here TokenAuthentication and already create token for every user.but I don't how to get token in javascript? For example, I wannt post a comment, using ajax like
$.ajax({
url: "/api/comment/",
type: "POST",
datatype: "json",
data: {"reply_id": "1", csrfmiddlewaretoken: "{{ csrf_token }}", and token here?},
});
But how can I get current user's token? cookies has set http-only and I can't access it. Maybe I should sent another ajax to get the token by using username(which I display on my website) to search the database first?
Any help is welcome, Thanks.
EDIT: Should I use localStorage instead?
You first need to retrieve the auth token by logging in using the users credentials. You then have an auth token which you can store in your localStorage for example.
The JS code for logging in looks roughly like this;
var credentials = {
username: "admin",
password: "abc123"
};
$.post("http://localhost:8000/api-token-auth/", credentials, function(auth) {
console.log("Logged in, auth token: ", auth.token);
}
This is probably a silly question, but I can't find an obvious response.
I'm developing a web application using (Geo)Django for the backend and Leaflet, among others, for the frontend. My point is I want to make a url call from my JS code to my Django backend. Something like this:
$.ajax({
type: 'POST',
url: '<A_URL_HERE>',
data: {"data":<MY_JSON_DATA>},
dataType: 'json',
success: function(responseData, textStatus, jqXHR) {
console.log("Data saved");
},
error: function (responseData, textStatus, errorThrown) {
console.log("Problem saving the data");
}
});
My problem is with the url. I know that cool URIs don't change, but for example, if I want to keep different dev/test/prod environments without changing that parameter, how should I do it? In the backend part, I'm following good practices for this kind of problems, but I have short experience with JS and frontend.
Many thanks in advance
Two possible solutions:
Use dynamically generated JavaScript, i.e. the JavaScript file is not a hardcoded static file. Instead it is a template which backend populates with variables (in particular URL);
Similar to the one above except that JavaScript is a hardcoded static file and for example you put your URLs in base HTML (which is generated from a template on the server side):
base.html
<script>window.urls = { "my_url": "{{ my_url }}" };</script>
my_script.js
$.ajax({
url: window.urls.my_url,
...
});
With this you can generate URLs based on you server settings.