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);
}
Related
In my Postman collection, I have a pre-request script that ensures I have a valid JWT token available for authentication. It looks similar to the following (I have removed the logic of checking expiration and only fetching a new token if needed):
function get_and_set_jwt() {
let base_url = pm.environment.get("BASE_URL")
pm.sendRequest({
url: base_url + '/api/auth/',
method: 'POST',
header: {
'content-type': 'application/json',
'cookie': ''
},
body: {
mode: 'raw',
raw: JSON.stringify({ email: pm.environment.get("USER_EMAIL_ADDRESS"), password: pm.environment.get("USER_PASSWORD") })
}
}, function (err, res) {
let jwt = res.json().token
postman.setEnvironmentVariable("JWT", jwt)
});
}
get_and_set_jwt();
I am attempting to set 'cookie': '' so that the request from this script will be made with no cookies. The backend I am working with sets a session cookie in addition to returning the JWT, but I want to force all future requests (when I need to renew the JWT) to not include that session information.
Unfortunately, if I check the Postman console, I see that the requests are still being sent with the cookie header, and the session cookie that was set by the earlier response. I have even tried overriding it by setting 'cookie': 'sessionid=""', but that just yields a request that includes two session ids in the cookie header (it looks like sessionid=""; sessionid=fasdflkjawew123sdf123;)
How can I send a request with pm.sendRequest with either a completely blank cookie header, or without the header at all?
First of all, I am pretty new to working with Rest APIs and tokens, I have learned the basics of Django and React and I've kinda made some projects using those, so I'm giving a shot at making a website with both of them.
Since, registering is simple with django-rest-auth, it's been handled with just POSTING the user data. However, when making a login, the token was returned and I simply do not know how to handle it. I have searched many articles about tokens, but they were all about JWT which returns an access token and a refresh token. However, django-rest-auth returns a single token and I saved it inside a cookie using a 'universal-cookie' in React. Since I'm making an e-commerce website, and I do want to add some functionality to the website by enabling the users to change their email, last name, first name and username, I do need to know the username of the account as it is unique.
So, I am wondering if it would be alright and a good practice to save the username inside a cookie, again using a universal-cookie. It'd also be appreciated if someone shows me a good article about "what to do with a token" or how to utilize it because I have little to none knowledge about it.
const handleLogin = async (e) => {
e.preventDefault();
const csrftoken = getCookie("csrf");
const url = "http://localhost:8000/rest-auth/login/";
const cookies = new Cookies();
await fetch(url, {
method: "POST",
headers:{
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: username,
password: password,
}),
}).then((response) => {
setResponseCode(response.status);
response.json().then((key) => {
cookies.set("token", key.key);
setIsClicked(true);
});
});
};`
Here is how I've been storing the token I get, and using it from navbar or other react components to check if the user has been logged in or not.
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 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.
I am building an app with AngularJS and using external API made with Django.
For API calls I'm using Restangular (but it's not the case because even with $http I get the same).
My default content-type for post calls is:
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
This is done just so I could send credentials when signing in win OAuth2:
var data = {
grant_type: 'password',
client_id: clientID,
client_secret: clientSecret,
username: username,
password: password
};
$http.post('http://server.com/api/oauth2/access_token/', data);
GET is done using default AngularJS configuration (application/json I guess).
So far so good, everything was working until... I was making POST requests and sending large JSON objects.
The configuration from above didn't work, so I changed those POST requests to application/json, and getting error response:
400: JSON parse error - No JSON object could be decoded
Tried the same with just jQuery - and it worked although I had to do JSON.strigify and in error debugging on Chrome Request Payload with jQuery looks like a proper object, and with AngularJS looks like this:
type=Feature&geometry=%5Bobject%20Object%5D&properties=%5Bobject%20Object%5D
(yes, by the way, I'm sending a valid GeoJSON object)
So I thought maybe JSON.stringify has something to do with this but after applying this to my object, the Request Payload from AngularJS is a mess:
0=%7B&1=%22&2=t&3=y&4=p&5=e&6=%22&7=%3A&8=%22&9=F&10=e&11=a&12=t&13=u&14=r&15=e&16=%22&17=%2C&18=%22&19=g&20=e&21=o&22=m&23=e&24=t&25=r&26=y&27=%22&28=%3A&29=%7B&30=%22&31=t&32=y&33=p&34=e&35=%22&36=%3A&37=%22&38=P&39=o&40=i&41=n&42=t&43=%22&44=%2C&45=%22&46=c&47=o&48=o&49=r&50=d&51=i&52=n&53=a&54=t&55=e&56=s&57=%22&58=%3A&59=%5B&60=1&61=9&62=.&63=0&64=8&65=3&66=2&67=4&68=1&69=2&70=2&71=4&72=2&73=8&74=8&75=9&76=%2C&77=5&78=0&79=.&80=2&81=4&82=2&83=4&84=0&85=2&86=0&87=7&88=2&89=3&90=6&91=8&92=9&93=%5D&94=%7D&95=%2C&96=%22&97=p&98=r&99=o&100=p&101=e&102=r&103=t&104=i&105=e&106=s&107=%22&108=%3A&109=%7B&110=%22&111=c&112=o&113=n&114=t&115=r&116=i&117=b&118=u&119=t&120=i&121=o&122=n&123=t&124=y&125=p&126=e&127=%22&128=%3A&129=1&130=2&131=1&132=4&133=5&134=%2C&135=%22&136=l&137=o&138=c&139=a&140=t&141=i&142=o&143=n&144=%22&145=%3A&146=%7B&147=%22&148=n&149=a&150=m&151=e&152=%22&153=%3A&154=%22&155=D&156=a&157=n&158='&159=s&160=%20&161=H&162=o&163=u&164=s&165=e&166=%22&167=%2C&168=%22&169=d&170=e&171=s&172=c&173=r&174=i&175=p&176=t&177=i&178=o&179=n&180=%22&181=%3A&182=n&183=u&184=l&185=l&186=%2C&187=%22&188=s&189=t&190=a&191=t&192=u&193=s&194=%22&195=%3A&196=n&197=u&198=l&199=l&200=%2C&201=%22&202=c&203=r&204=e&205=a&206=t&207=e&208=d&209=_&210=a&211=t&212=%22&213=%3A&214=%22&215=2&216=0&217=1&218=4&219=-&220=0&221=4&222=-&223=3&224=0&225=T&226=1&227=0&228=%3A&229=2&230=4&231=%3A&232=5&233=8&234=.&235=9&236=3&237=7&238=Z&239=%22&240=%2C&241=%22&242=i&243=d&244=%22&245=%3A&246=4&247=5&248=%7D&249=%7D&250=%7D
Any help? What I'm doing wrong? Or it has something to do with Django API? Should we change something in it?
SOLVED
The problem was caused by serialiser (my interpretation of jQuery's $.param). Apparently I needed this for sending credentials for the OAuth2 but not for any other POST request.
Although I still don't know why it is like that.
try this
var data = {
grant_type: 'password',
client_id: clientID,
client_secret: clientSecret,
username: username,
password: password
};
$http.post('http://server.com/api/oauth2/access_token/', angular.toJson(data));
Include jquery and try this
$http({
method: 'POST',
url: 'http://server.com/api/oauth2/access_token/',
data: $.param(data)
});