I have a django project, using django-rest-framework to create api.
Want to use token base authentication system so api call for (put, post, delete) will only execute for authorized user.
I installed 'rest_framework.authtoken' and created token for each users.
So, now from django.contrib.auth.backends authenticate, it returns user, with auth_token as attribute. (when loged in successfully).
Now my question is how can I send the token with post request to my api and
at api side how can I verify if token is valid and belongs to the correct user?
Are there any methods in app rest_framework.authtoken to validate given user and its token?
not found this very useful!
Update (changes I made):
Added this in my settings.py:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
)
}
Also sending Token in my header but its still not working:
if new_form.is_valid:
payload= {"createNewUser":
{ "users": request.POST["newusers"],
"email": request.POST["newemail"]
}
}
headers = {'content-type' : 'application/json',
'Authorization': 'Token 6b929e47f278068fe6ac8235cda09707a3aa7ba1'}
r = requests.post('http://localhost:8000/api/v1.0/user_list',
data=json.dumps(payload),
headers=headers, verify=False)
"how can I send the token with post request to my api"
From the docs...
For clients to authenticate, the token key should be included in the Authorization HTTP header. The key should be prefixed by the string literal "Token", with whitespace separating the two strings. For example:
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
"at api side how can I verify if token is valid and belongs to the correct user?"
You don't need to do anything, just access request.user to return the authenticated user - REST framework will deal with returning a '401 Unauthorized' response to any incorrect authentication.
To answer the first half of your question:
how can I send the token with post request to my api
You can use the Python requests library. For the django-rest-framework TokenAuthentication, the token needs to be passed in the header and prefixed by the string Token (see here):
import requests
mytoken = "4652400bd6c3df8eaa360d26560ab59c81e0a164"
myurl = "http://localhost:8000/api/user_list"
# A get request (json example):
response = requests.get(myurl, headers={'Authorization': 'Token {}'.format(mytoken)})
data = response.json()
# A post request:
data = { < your post data >}
requests.post(myurl, data=data, headers={'Authorization': 'Token {}'.format(mytoken)})
I finally have the django "rest-auth" package working for token authentication.
If this helps, here is the client-side jQuery code that worked for me, after you successfully log in and receive the "auth_token":
var user_url = {API URL}/rest-auth/login
var auth_headers = {
Authorization: 'Token ' + auth_token
}
var user_ajax_obj = {
url : user_url,
dataType : 'json',
headers: auth_headers,
success : function(data) {
console.log('authorized user returned');
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log('error returned from ' + user_url);
}
};
$.ajax(
user_ajax_obj
);
If you are using coreapi. To add the Authorisation you do
import coreapi
auth = coreapi.auth.TokenAuthentication(scheme='Token', token=token_key)
Then you can do
client = coreapi.Client(auth=auth)
response = client.get(my_url)
Related
User Data
let final_data = {
'personal_data': {
'first_name': data.first_name,
'password': data.password,
'phone': data.phone,
'username': data.username,
'email': data.email,
'image': data.profile[0]
},
'address_data': {
"address_1": data.address_1,
"address_2": data.address_2,
"city": data.city,
"pin_code": data.pin_code,
"state": data.state,
"country": data.country
}
}
Above Code is my form data which i have passed.
I had also tried to pass this data using json.stringify still it not works
AXIOS POST Request
import API from "../Axios/AxiosService"
const registerUser = (data) => API.post(`registration/`, data)
export default { registerUser }
HEADERS
if (config.url = 'registration/') {
requestOptions['headers'] = {'Content-Type': 'multipart/form-data;boundary=----WebKitFormBoundaryyrV7KO0BoCBuDbTL', 'Accept' : 'application/json'}
} else {
requestOptions['headers'] = {'Content-Type': 'application/json'}
}
if (localStorage.getItem("access_token")) {
requestOptions['headers'] = {"Authorization": "Token " + localStorage.getItem("access_token")}
}
Above Code is AXIOS POST Request and also Passed headers accrodingly. Using Application/Json i get all data except image and from data i also tried to pass data.profile instead of data.profile[0] but it didn't works.
Django Rest Framework error
**In POST method of Django Rest Framework i had used below listed ways to get but in all methods i didn't get any data **
request.POST
request.data
request.Files
You should give the queryset to UserRegistrationView like;
class UserRegistrationView(generics.CreateAPIView):
queryset = User.objects.all()
serialier_class = UserSerializer
In React inspite of passing Content-type="multipart/form-data" in to POST request it will not pass image object in backend.
So we have to convert whole data in to formdata and then pass in POST Request.
That's how I solved my error.
Have a look at the Example
I've followed everything mentioned in both documentation of Django rest-framework and Flutter http but still getting the error ..here is my code :
Django
Settings
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
]
}
View
#csrf_exempt
#permission_classes(["isAuthenticated"])
#api_view(['POST'])
def chanage_image(request):
data = {}
if request.method == "POST":
token = request.META['HTTP_AUTHORIZATION'][6:]
lang = request.META['HTTP_LANG']
image = request.data['image']
main_user = Token.objects.get(key=token).user
app_user = AppUser.objects.get(main_user=main_user)
format, imgstr = image.split(';base64,')
ext = format.split('/')[-1]
data = ContentFile(base64.b64decode(imgstr), name='temp.' + ext) # You can save this as file instance.
app_user.image = data
app_user.save()
data = {"success": True, "details": AppUserSerializer(
app_user).data, "message": "Image changed" if lang == "en" else "تم تغيير الصورة"}
return Response(data, headers=get_headers())
URLS
path('chanage_image/', chanage_image,name="chanage_image"),
Flutter
Request
Map<String, dynamic> body = {
"image": base64Image,
};
Future<UserModel> changePlayerImage(Map<String, dynamic> body) async {
return await httpClient.post('api/user/change-image',
body: body,
headers: {'referer': 'https://www.l-dawri.com/'}).then((response) {
print(response.body);
return UserModel.fromJson(response.body);
});
}
but still in the end am always getting this error :
CSRF verification failed. Request aborted.
You are seeing this message because this site requires a CSRF cookie when submitting forms.
First you don't sent authorization token into header request while use from drf TokenAuthentication
Also into drf is better you use from class view api(like inheritance from APIView) replace def view's
If I have a post request with this JSON :
{
"user_id":230,
"name":"Anthony"
}
I can extract the name by :
name = json.loads(request.body).get("name")
Now I have a GET request in which I am passing bearer token.
How should I extract it in Django?
You can access the authorization header with request.META['HTTP_AUTHORIZATION']
So, i new in django and djangorestframework. i followed their tutorial in their page. http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions/
in that tutorial, you can login as django user from djangorestframework api login page. my question is, if i want to make a CLI or GUI application and using requests module to post a content to the API, but the API must be loggged in first. how i do that?
In DRF, you can add additional package for simple token-based Authentication. Add rest_framework.authtoken to INSTALLED_APPS. To make HTTP(S) request to client you pass the authorization token like this Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
For testing, you can use curl
curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
Read more...
You can set that a user must be authenticated at all times as default setting in settings.py (in your web server project):
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
More info about that here.
In your web client project, like one of the comments on your questions mentions, you must add an Authentication header in the HTTP messages you send to the web server. An example (TypeScript Angular application implementation) would be:
import {Injectable} from '#angular/core';
import {HttpClient, HttpHeaders} from '#angular/common/http';
import {Observable} from 'rxjs/Observable';
import {Spacecraft} from '../model/spacecraft';
/* Create the authentication headers for the HTTP requests to the DRF project's API.
* Note: uses btoa(): base-64 encoding of ASCII string, see https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/btoa.
*/
const basicAuthenticationToken = btoa(environment.REST_API.username + ':' + environment.REST_API.password);
const httpOptions = {
headers: new HttpHeaders({
'Authorization': `Basic ${basicAuthenticationToken}`
})
};
#Injectable()
export class APICommunicationService {
constructor(private http: HttpClient,
private notificationsService: NotificationsService) {
}
getSpacecraftInfo(url: string): Observable<Spacecraft> {
return this.http.get<Spacecraft>(url, httpOptions)
}
}
I have an app which needs to redirect to another url from outside with some POST data. I have the CSRF token value to the other app. How do I construct a simple POST request with requests library in Python??
csrf_token = "kjsbfckjsdnfcksdnkl"
post_data = {'email': email, 'answer': answer}
response = request.post(URL, data=post_data)
Where do I add the CSRF token?
You can either send the CSRF token as a POST parameter or a HTTP header.
Edit: a Referer HTTP header is also required by Django's CSRF protection. It needs to have the same origin as the request.
Using POST parameters:
post_data = {'email': email, 'answer': answer, 'csrftoken': csrf_token_value}
headers = {'Referer': URL}
response = request.post(URL, data=post_data, headers=headers)
Using HTTP headers:
post_data = {'email': email, 'answer': answer}
headers = {'X-CSRFToken': csrf_token_value, 'Referer': URL}
response = request.post(URL, data=post_data, headers=headers)
Another workaround is to use csrf_exempt decorator.
https://docs.djangoproject.com/en/3.2/ref/csrf/#django.views.decorators.csrf.csrf_exempt .
In case you are using a recent Django with CsrfMiddleware add it to the post_data dict:
post_data = {'email': email, 'answer': answer, 'csrfmiddlewaretoken': 'yourtoken'}
Check a form if the variable name is correct.
If you want to redirect on the same server, just call die other view function.
Take a look at the official documentation, which covers sending a POST request with a CSRF token.
CSRF tokens are stored in cookies (as far as I know). Since that's the case, you can store the cookie value as some variable, then use that value in your request.
I suggest you to use session objects of request library.
Moreover, if you’re making several requests to the same host, the underlying TCP connection will be reused, which can result in a significant performance increase and A Session object has all the methods of the main Requests API.