How to GET request if login_required in DJango - django

Here my API:
#login_required
#api_view(['GET'])
def get_order(request):
order_list = Order.objects.values("user_name",
"user_surname",
"order_date").all()
return HttpResponse(json.dumps([x for x in order_list])
The problem is when i add #login_required, i'm trying to do a Postman GET request using BASIC authentication with username and password.
If i remove the #login_required, i can perform a succesful GET request without auth in Postman.

First, login with your browser. Next, locate where the corresponding authentication cookie is stored in your browser. Copy it to your clipboard. Finally, paste the cookie and pass it along with the GET request in Postman:
The name of the cookie is sessionid.

Related

How to implement admin login and logout using Django REST framework?

I have been given a task to authenticate admin login programmatically and logout as well.
I am able to to do login but on logged out when I check which user I am logging out it says AnonymousUser. How can I make sure I log out current user which is logged it.
I am using Django REST framework and testing it on Postman.
#api_view(["POST"])
def adminLogin(request):
if(request.method=="POST"):
username = request.data["username"]
password = request.data["password"]
authenticated_user = authenticate(request,username=username, password=password)
if authenticated_user != None:
if(authenticated_user.is_authenticated and authenticated_user.is_superuser):
login(request,authenticated_user)
return JsonResponse({"Message":"User is Authenticated. "})
else:
return JsonResponse({"message":"User is not authenticated. "})
else:
return JsonResponse({"Message":"Either User is not registered or password does not match"})
#api_view(["POST"])
def adminLogout(request):
print(request.user)
logout(request)
return JsonResponse({"message":"LoggedOut"})
Logging in/logging out with a REST API makes not much sense. The idea of logging in/logging out, at least how Django implements it, is by means of the session, so with a cookie that has the session id.
API clients like Postman usually do not work with cookies: each request is made more or less independent of the previous one. If you thus make the next request without a reference to the session, then the view will not link a user to that request. Clients like AJAX that runs on the browser of course can work with cookies, since these are embedded in the browser that manages cookies. You can work with cookies in postman as specified in this tutorial [learning postman], but this is usually not how an API is supposed to work.
This is why APIs usually work with a token, for example a JWT token. When authenticating, these are given a token that might be valid for a short amount of time, and subsequently it uses that token to make any other request that should be authorized.
As the Django REST framework documentation on TokenAuthentication [drf-doc] says, you can define views that create, and revoke tokens. The page also discusses session authentication that thus can be used for AJAX requests.
But likely you are thus using the wrong means to do proper authentication for your REST API, and you thus might want to work with a token like a JWT token instead.

How to get POST parameters in a Django view protected by #login_required?

Django's login_required decorator requires a login before proceeding to any functionality in a view function. If a user is not logged in, they will be redirected through a login screen.
If the HTTP request is a GET, Django sometimes puts the GET destination in a parameter ("next"). Or, Django also has a LOGIN_REDIRECT_URL setting that is a URL a user is forwarded to after login.
If the HTTP request is a POST, that POST data is lost during the login process.
What is the best way to preserve the original URL and POST data for the original POST request, and re-post that data after the user is logged in?
I imagine putting something in a session, but I'd have to intercept the POST data and URL on the way through login_required. The best practice is not obvious to me.

Jsonresponse in Django working in browser but not in PostMan or Angular

I am trying to send a JSON response from Django back-end to my angular front-end.
When I make the request I receive nothing in Postman or Angular but,opening the link in browser seems to be returning the correct result
My View is :
#api_view(['GET'])
def my_view(request):
print(request.user.username)
return JsonResponse({'username': request.user.username})
When I open http://127.0.0.1:8000/accounts/get_username/ in browser I receive
{"username": "aditya8010"} on the web page.
But when i do a get request using POSTMAN I recieve
{
"username": ""
}
Same with Angular
this.http.get("http://127.0.0.1:8000/accounts/get_username/").subscribe((res) => {
this.username = JSON.stringify(res["username"])
console.log(this.username," ", res)
})
this code also prints an empty username string.
Another thing I have noticed is that my print statement in the view does print anything random I put in there when called from POSTMAN or Browser but when I use request.user.username it doesnt print anything when called by POSTMAN.
And each time the response code is 200
What am I doing wrong.
When you're sending the request you are not providing authentication credentials (i.e. something that identifies the user that is sending the request). How do you obtain this credentials?
You need to establish an authentication method. There are several but I recommend using Token authentication with knox package. Basically, you have an endpoint that logins the user with his username and password (normal json post request) and that endpoint returns a token. This token is what identifies the user. You send this token in the header of each request you need to be authenticated. That means you probably should include an IsAuthenticated permission for the view. In postman:
API view:
from rest_framework.permissions import IsAuthenticated
#api_view(['GET'])
#authentication_classes([IsAuthenticated])
def my_view(request):
print(request.user.username)
return JsonResponse({'username': request.user.username})
When it is in a browser, your login information is remembered in the session. When using postman or Angular, you need to provide the user's information in the request header manually.

Passing django user as redirect request header

I have a (non-django) application A that requires a username to login. This app allows for pre authorization, which I want to provide from my django application B. However app A requires that the username is set as a remote_user request header. What I tried to do is create a view in django app B that redirects to app A passing a remote_user header.
urls.py
url(r'^{0}to_app_a$'.format(DJANGO_BASE), 'app.views.to_app_a')
views.py
def to_app_a(request):
response = redirect('http://app_a')
response['remote_user] = request.user
return response
The problem with that is that the header is lost on redirect and never reaches the request to http://app_a external app. It has been suggested to use cookies instead, but unfortunately app A won't accept anything else than a remote_user request header.
Has anyone come up with a solution to such issue?
Thank you

Test REST service based on request.user

I build SPA on Django and I want to GET and POST JSON data based on request.user.
Something like this:
def get(self, *args, **kwargs):
return {
"data": [
i.get_json() for i in Customer.objects.filter(pk=self.request.user.pk)]
}
But I confuse, how it possible to put my user in request by REST service, like "Postman" or "Curl".
Postman has "Authorization" field, so I put login and password into it and my headers update with:
Authorization Basic YWdlbmN5X3NwYUBtYWlsLnJ1OjExMTEx
And I test it with curl:
curl -u myuser:11111 http://127.0.0.1:8000/api/myurl/
But user still - AnonymousUser
It could work with angular later, but I don't understand how I can test it now.
I found solution. I need to login with my user first and take sessionid from Cookie, then put sessionid in request.
Postman has nice extension named "Postman Interceptor", it put all session from browser into request authomaticly.