Authentication on Post DRF - django

I got an error on my DRF. when I try to authenticate using a post method.
the token is the correct for the admin user. when I use a safe method it is sucessfull, but with the post method no, it doesn't authenticate
my view
class SpecialistListView(ListCreateAPIView):
authentication_classes = (OAuth2Authentication,)
permission_classes = (permissions.IsAdminUser,)
queryset = Specialist.objects.all()
serializer_class = SpecialistSerializer
I don't understand why the status of the code returned is HTTP 401 Unauthorized.
It does'nt work on testing. I check that in postman is succesfull.
I'm using APIClient from rest_framework.test import APIClient
my test_client
client = APIClient()
client.credentials(HTTP_AUTHORIZATION='Bearer EGsnU4Cz3Mx5bUCuLrc2hmup51sSGz')
class CreateSpecialist(APITestCase):
fixtures = ['data','data2']
def setUp(self):
self.valid_payload = {
'username': 'julia',
'nick': 'julia',
'password': 'intel12345',
"first_name": "juliana",
"last_name": "garzon"
}
def test_create_specialist(self):
response = self.client.post(
reverse('specialists'),
data=json.dumps(self.valid_payload),
content_type='application/json'
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)

I just add the credentials before the post and it works! :D
def test_create_specialist(self):
self.client.credentials(HTTP_AUTHORIZATION='Bearer EGsnU4Cz3Mx5bUCuLrc2hmup51sSGz')
response = self.client.post(
reverse('specialists'),
data=json.dumps(self.valid_payload),
content_type='application/json'
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)

Related

Authentication error 401 for jwt token in DRF tests

I have a problem getting jwt authorization for get method in test. my tests:
class ImageViewsTests(APITestCase):
def setUp(self):
self.test_user = User.objects.create_user(**TEST_USER)
TEST_IMAGE['created_by'] = self.test_user
self.temp_image = Image.objects.create(**TEST_IMAGE)
self.token = RefreshToken.for_user(self.test_user)
def test_images_list(self):
url = reverse('jwt-create')
client = APIClient()
client.credentials(HTTP_AUTHORIZATION=f'JWT {self.token.access_token}')
response = self.client.get('/image/', data={'format': 'json'})
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, TEST_IMAGE)
Tests return AssertionError: 401 != 200.
Token is returned correctly but does not work in header. For example everything is fine in Postman. postman
I did something else like this and I also get no authorization
def test_images_list(self):
url = reverse('jwt-create')
client = APIClient()
resp = self.client.post(url, {'email':TEST_USER['email'], 'password':TEST_USER['password']}, format='json')
self.assertEqual(resp.status_code, status.HTTP_200_OK)
client.credentials(AUTHORIZATION=f'JWT {resp.data["access"]}')
response = self.client.get('/image/', data={'format': 'json'})
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, TEST_IMAGE)
Im using Djoser, jwt, DRF. Where am I making a mistake?
Try this for setting the credentials:
self.token = RefreshToken.for_user(self.test_user)
client.credentials(HTTP_AUTHORIZATION=f'Bearer {self.token.access_token}')

auth_token for unittest in Django

I've been trying to test my login system using the following code
from django.test import TestCase, Client
from rest_framework.test import force_authenticate
class DeckTestCase(TestCase):
#classmethod
def setUp(cls):
test_user1 = User.objects.create(first_name='tester',username='test1', password='123', email='testuser#something.com')
def test_if_logged(self):
factory = Client()
user = User.objects.get(username='teste1')
request = factory.post('/login', {'username': 'test1', 'password': '123'}, format='json')
force_authenticate(request,user=user)
print(request)
But i keep getting this response, which is 401 (Unauthorized)
<Response status_code=401, "application/json">
Can someone help me? I don't know how do I send an auth_token with test_if_logged
You should use .create_user(…) [Django-doc] to create a user, this will set a hashed password for that user:
#classmethod
def setUp(cls):
test_user1 = User.objects.create_user(
first_name='tester',
username='test1',
password='123',
email='testuser#something.com'
)

What is the difference between using Django's APIClient from a unit test or from a Django shell

I am trying to write unit tests for an Django OAuth2 API. I am using Django's APIClient library. if I use it from a Django shell. it works perfectly, but if I use is in a unit test, the POST request to the view returns a 401 error: {"error": "invalid_client"}
[ EDITED ]
### This works perfectly in a Django Shell
from rest_framework.test import APIClient
client = APIClient()
response = client.post('/authentication/register/', {"username": "testuser9", "password": "1234abcd"},
header={"Content-Type": "application/json"})
[ EDITED ]
### This unit test fails with a 401
class OAuth2TestCase(APITestCase):
def test_user_registration_valid_data(self):
"""Tests register view"""
client = APIClient()
response = client.post('/authentication/register/',
{"username": "testuser88", "password": "1234abcd"},
header={"Content-Type": "application/json"})
[ EDITED ]
### The view
#api_view(['POST'])
#permission_classes([AllowAny])
def register(request):
'''
Registers user to the server. Input should be in the format:
{"username": "username", "password": "1234abcd"}
'''
serializer = CreateUserSerializer(data=request.data)
logger.info("Request Data {}".format(request.data))
if serializer.is_valid():
serializer.save()
data={
'grant_type': 'password',
'username': request.data['username'],
'password': request.data['password'],
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
}
test_request = HttpRequest()
test_request.POST = request.POST.copy()
test_request.POST = data
test_request.method = 'POST'
test_request.META = request.META
test = TokenView()
test_response = test.post(request=test_request)
return test_response
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
What are the differences between making the APIClient request from the Django shell and making it from a unit test?

Unit Test Using Forcing Authentication Django Rest Framework

I'm building RESTful API services using django rest framework, I've reached the point where i have to create an automated test for my RESTful API services.
The sessionList api require token authentication, in case the user doesn't have the token he won't be able to access the session collection.
The api worked fine when I've tested it using POSTMAN and the real browser.
SessionList:
class SessionList(generics.ListCreateAPIView):
authentication_classes = [TokenAuthentication, ]
permission_classes = [IsAuthenticated, ]
throttle_scope = 'session'
throttle_classes = (ScopedRateThrottle,)
name = 'session-list'
filter_class = SessionFilter
serializer_class = SessionSerializer
ordering_fields = (
'distance_in_miles',
'speed'
)
def get_queryset(self):
return Session.objects.filter(owner=self.request.user)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
Then i've created an automated test using DRF test
RunningSessionTest:
class RunningSessionTest(APITestCase):
def test_get_sessions(self):
factory = APIRequestFactory()
view = views.SessionList.as_view()
user = User.objects.create_user(
'user01', 'user01#example.com', 'user01P4ssw0rD')
request = factory.get('http://localhost:8000/sessions/')
force_authenticate(request, user=user)
response = view(request)
assert Response.status_code == status.HTTP_200_OK
def test_get_sessions_not_authenticated_user(self):
factory = APIRequestFactory()
view = views.SessionList.as_view()
user = User.objects.create_user(
'user01', 'user01#example.com', 'user01P4ssw0rD')
request = factory.get('http://localhost:8000/sessions/')
response = view(request)
assert Response.status_code == status.HTTP_401_UNAUTHORIZED
The issue: in both cases, if the user has the token or not the response value is HTTP_200_OK
I've tried to solve the problem by trying different methods to implement the test. I've used APIRequestFactory, Also i've used the APIClient but i got the same result. To be honest after reading the document many times i couldn't understand the differences between the APIClient and the APIRequestFactory.
The result of the test :
Traceback (most recent call last):
File "C:\python_work\DjnagoREST\01\restful01\RunKeeper\tests.py", line 67, in test_get_sessions_not_authenticated_user
assert Response.status_code == status.HTTP_401_UNAUTHORIZED
AssertionError
I will be grateful to your help.
I guess you will need to change Response.status_code to response.status_code.
As it turned out Response.status_code (as from rest_framework.response.Response)
is equal to 200 :D

Unabe to get token from DRF get-token api

my custom signup api
from rest_framework import viewsets
from rest_framework import serializers
class SignupSerializer(serializers.Serializer):
email = serializers.EmailField(required=True)
password = serializers.CharField(required=True, write_only=True)
def validate_email(self, val):
try:
User.objects.get(username=val)
raise serializers.ValidationError("Email-ID already Exist")
except User.DoesNotExist:
return val
class SignupView(viewsets.ModelViewSet):
serializer_class = SignupSerializer
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
data = serializer.data
email = data.get('email')
password = data.get('password')
u = User(email=email, username=email)
u.set_password(password)
u.save()
data = {
'message': 'Successfully Created!',
'data': {'id': u.id, 'email': email},
}
return Response(data)
Toekn get api
from rest_framework.authtoken import views
urlpatterns = [
url(r'^api-token-auth/', views.obtain_auth_token),
]
when I hit signup api, it returns the success response, I mean
{
'message': 'Successfully Created!',
'data': {'id': 1, 'email': 'xyz#gmail.com'} }
but when I try to generate/get token for this user using above token api, it says ..invalid credentials?
{
"non_field_errors": [
"Unable to log in with provided credentials."
]
}
however if I create a user using management command createsuperuser and use same api to get token it works?
is there someting wrong in signup api?
You should remove write_only=True from your serializer. that would fix the error.
The Error message actually tells you that your request is not able to reach the view, this happens because one of the middlewares raises an error.
The easiest (but pbly not very secure) solution would be to return the API token on successful signup, or to add another View with a login (which returns an token).
For a definite answer you would need to provide more information like the configuration for your Authentication Backends.
You can find here more Informations about Authentication in DRF
http://www.django-rest-framework.org/api-guide/authentication/#how-authentication-is-determined