I tried to create a client that uses django test client and make a get request with token authentication. But I get a 401 error so something is wrong ..Of course this also happens for post.
I was looking for different solutions but nothing works.
this is part of the code:
from django.test import Client
class MyClient:
def __init__(self):
self.client = Client()
self.token = None
def get(self, url):
if self.token is not None:
new_url = base + url
result = self.client.get(new_url, headers={'Content-Type': 'application/json','Authorization': 'Token {}'.format(self.token)})
else:
result = self.client.get(url)
return result
def login(self, username, password):
payload = {
"username": username,
"password": password
}
response = self.post_without_auth('/api/auth/token_auth/',payload)
if response.status_code is 200:
self.token = response.json()['token']
return response
def post_without_auth(self, url, payload):
response = self.client.post(url, payload)
return response
def current_user(self):
response = self.get('/api/current_user/')
return response
call the method post which will set the token value
def get(self, url):
self.post(username, password)
if self.token is not None:
new_url = base + url
result = self.client.get(new_url, headers={'Content-Type': 'application/json','Authorization': 'Token {}'.format(self.token)})
else:
result = self.client.get(url)
return result
def login(self, username, password):
payload = {
"username": username,
"password": password
}
response = self.post_without_auth('/api/auth/token_auth/',payload)
if response.status_code is 200:
self.token = response.json()['token']
return response
Related
I'm trying to connect rest framework views to a template, the get method is working properly but when posting datas it gives me the error :
views.py:
class Login(APIView):
serializer_class = LoginSerializer
permission_classes = [IsAnonymous, ]
template_name = 'accounts/login.html'
renderer_classes = [TemplateHTMLRenderer]
style = {'template_pack': 'rest_framework/vertical/'}
def get(self, request):
serializer = self.serializer_class()
return Response({'serializer': serializer, 'style': self.style})
def post(self, request):
payload = request.data
serializer = self.serializer_class(data=payload)
if serializer.is_valid():
user = authenticate(request,
username=payload['username'],
password=payload['password']
)
if user:
login(request, user)
response = {
'message': 'you logged in successfully!'
}
code = status.HTTP_200_OK
else:
response = {
'message': 'your username or password is wrong!'
}
code = status.HTTP_401_UNAUTHORIZED
else:
response = {
'error': serializer.errors
}
code = status.HTTP_403_FORBIDDEN
return Response(data=response, status=code)
I don't know where am I doing wrong , I appreciate if anyone can help me in this case
I want to restrict multiple user logins like when a user tries to login again i want to give him a error saying you already have a active session
This is how i am doing it right now
my middleware.py
class MySessionMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
print(request.user.is_authenticated)
if request.user.is_authenticated:
print('here2')
try:
user = LoggedInUser.objects.create(user=request.user)
except:
user = LoggedInUser.objects.filter(user=request.user).first()
print(type(user))
if not request.session.session_key:
request.session.save()
prev_session_key = request.user.logged_in_user.session_key
print(prev_session_key)
if prev_session_key:
print(prev_session_key)
print(request.session.session_key)
print('here5')
#check whether old key is same as current
print('here inside user.session_key')
if prev_session_key != request.session.session_key:
return JsonResponse("you already have a active session kindly logout from that",
status=400, safe=False)
user.session_key = request.session.session_key
user.save()
return response
my models.py
class LoggedInUser(models.Model):
user = models.OneToOneField(User, related_name='logged_in_user', on_delete =models.CASCADE, null=True, blank=True)
session_key = models.CharField(max_length=32, null=True, blank=True)
But this approach is not working as previous session key always comes out to be None , please suggest changes in my approach , i tried many solutions but they didnt work
my login view
class UserLoginView(generics.RetrieveAPIView):
"""
View for a user to login through 1FA.
The view provides a post request that accepts a email and password.
Returns a jwt token as a response to authenticated user.
"""
permission_classes = ()
serializer_class = UserLoginSerializer
def post(self, request):
"""
POST request to login a user.
"""
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
response = {
"success": "True",
"message": "User logged in successfully",
"token": serializer.validated_data["tokens"],
"user_name": serializer.validated_data["user_name"],
}
status_code = status.HTTP_200_OK
return Response(response, status=status_code)
Remove your logic from session middleware, add them in login view.
class UserLoginView(generics.RetrieveAPIView):
"""
View for a user to login through 1FA.
The view provides a post request that accepts a email and password.
Returns a jwt token as a response to authenticated user.
"""
permission_classes = ()
serializer_class = UserLoginSerializer
def post(self, request):
"""
POST request to login a user.
"""
if (request.user.is_authenticated):
response = {
"success": "False",
"message": "User already logged in!",
}
return Response(response, status=400)
else:
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
response = {
"success": "True",
"message": "User logged in successfully",
"token": serializer.validated_data["tokens"],
"user_name": serializer.validated_data["user_name"],
}
status_code = status.HTTP_200_OK
return Response(response, status=status_code)
This was working just fine before I tried to add social authentication to the project, and now when I send the verification email with the token, the token verifier says that the token is not valid!
class ResendVerifyEmail(APIView):
serializer_class = RegisterSerialzer
def post(self, request):
data = request.data
# email = data.get('email')
email = data['email']
print(email)
try:
user = User.objects.get(email=email)
# print('hello')
if user.is_verified:
return Response({'msg':'User is already verified','status':'status.HTTP_400_BAD_REQUEST'})
print (user.username)
token = RefreshToken.for_user(user).access_token
current_site= get_current_site(request).domain
relativeLink = reverse('email-verify')
absurl = 'http://'+current_site+relativeLink+"?token="+str(token)
email_body = 'Hi '+ user.username + ' this is the resent link to verify your email \n' + absurl
data = {'email_body':email_body,'to_email':user.email,
'email_subject':'Verify your email'}
Util.send_email(data)
return Response({'msg':'The verification email has been sent','status':'status.HTTP_201_CREATED'}, status=status.HTTP_201_CREATED)
except User.DoesNotExist:
return Response({'msg':'No such user, register first','status':'status.HTTP_400_BAD_REQUEST'})
class VerifyEmail(APIView):
serializer_class = EmailVerificationSerializer
def get(self, request):
token = request.GET.get('token')
try:
payload = jwt.decode(token, settings.SECRET_KEY)
# print('decoded')
user = User.objects.filter(id=payload['user_id']).first()
# print(user)
if user.is_verified:
return Response({'msg':'User already verified!'}, status=status.HTTP_400_BAD_REQUEST)
else:
user.is_verified = True
# user.is_authenticated = True
user.is_active = True
# if not user.is_verified:
user.save()
return Response({'email':'successfuly activated','status':'status.HTTP_200_OK'}, status=status.HTTP_200_OK)
# except jwt.ExpiredSignatureError as identifier:
except jwt.ExpiredSignatureError:
return Response({'error':'Activation Expired','status':'status.HTTP_400_BAD_REQUEST'}, status=status.HTTP_400_BAD_REQUEST)
# except jwt.exceptions.DecodeError as identifier:
except jwt.exceptions.DecodeError:
return Response({'error':'invalid token','status':'status.HTTP_400_BAD_REQUEST'}, status=status.HTTP_400_BAD_REQUEST)
also, I have added these in settings.py
AUTHENTICATION_BACKENDS = (
'social_core.backends.facebook.FacebookOAuth2',
'django.contrib.auth.backends.ModelBackend',
)
I get 'jwt.exceptions.DecodeError'
This did the job
payload = jwt.decode(token, settings.SECRET_KEY, algorithms='HS256')
i am new in django, i require login with user and password or facebook, i am using rest framework for api endpoints. ¿How i can do it?
i try with:
django-rest-framework-social-oauth2 but don't work for my because i needs save additional info from user after first enter.
I expect have 2 endpoint one sending user and password and another sending facebook auth token
Here's sample code for user login for Django Rest Framework:
class Login(APIView):
#csrf_exempt
def dispatch(self, *args, **kwargs):
return super(Login, self).dispatch(*args, **kwargs)
#staticmethod
def post(request):
request_data = JSONParser().parse(request)
if 'email' in request_data and 'password' in request_data:
try:
validate_email(request_data['email'])
except ValidationError:
return JsonResponse({'result': 'E-mail is invalid'}, status=400)
user = authenticate(email=request_data['email'], password=request_data['password'])
if user is not None:
if user.is_active:
try:
token = Token.objects.get(user=user)
except Token.DoesNotExist:
token = Token.objects.create(user=user)
return JsonResponse({'result': 'success', 'token': token.key, 'id': user.id}, status=200)
return JsonResponse({'result': 'E-mail or password is incorrect'}, status=400)
return JsonResponse({'result': 'E-mail or password is empty'}, status=400)
Here's sample for FB login code for Django Rest Framework (from my test project):
class FbLogin(APIView):
authentication_classes = (authentication.TokenAuthentication,)
permission_classes = (permissions.AllowAny,)
#csrf_exempt
def dispatch(self, *args, **kwargs):
return super(FbLogin, self).dispatch(*args, **kwargs)
#staticmethod
def post(request):
request_data = JSONParser().parse(request)
if 'access_token' in request_data:
response = requests.get(
url='https://graph.facebook.com/v2.5/me/',
params={
'access_token': request_data['access_token'],
'fields': 'email,first_name,last_name',
},
)
json_response = json.loads(response.text)
if 'error' not in json_response:
response_photo = requests.get(
url='https://graph.facebook.com/v2.5/%s/picture' % json_response['id'],
params={
'redirect': 'false',
'type': 'large',
},
)
response_photo_json = json.loads(response_photo.text)
response_friends = requests.get(
url='https://graph.facebook.com/v2.5/me/friends/',
params={
'access_token': request_data['access_token'],
'limit': 300,
},
)
generated_password = get_random_string(10, '0123456789abcdefghijklmnopqrstuvwxyz')
try:
json_response_email = json_response['email']
except:
first_name = json_response['first_name'].lower()
last_name = json_response['last_name'].lower()
id = json_response['id']
json_response_email = first_name + last_name + id + '#facebook.com'
try:
current_user = User.objects.get(email=json_response_email)
current_user.set_password(generated_password)
current_user.save()
except User.DoesNotExist:
new_user = User.objects.create_user(email=json_response_email,
password=generated_password)
new_user.provider_id = json_response['id']
new_user.provider_type = 'facebook'
if 'first_name' in json_response:
new_user.first_name = json_response['first_name']
if 'last_name' in json_response:
new_user.last_name = json_response['last_name']
new_user.save()
photo_name = urlparse(response_photo_json['data']['url']).path.split('/')[-1].split('?')[-1]
photo_content = urllib.request.urlretrieve(response_photo_json['data']['url'])
new_user.profile_photo.save(photo_name, File(open(photo_content[0], 'rb')), save=True)
user = authenticate(email=json_response_email, password=generated_password)
try:
token = Token.objects.get(user=user)
except Token.DoesNotExist:
token = Token.objects.create(user=user)
if user is not None:
if user.is_active:
fullname = json_response['first_name'] + ' ' + json_response['last_name']
return JsonResponse({'result': 'success', 'token': token.key, 'name': fullname}, status=200)
return JsonResponse({'result': 'User access token is incorrect'}, status=400)
I have a view, It will send requests to http://127.0.0.1:80/o/token/
I want to know can I directly call the view /o/token/ and get the result ?
And do not need to import requests to send it
class GetAccessToken(APIView):
def post(self, request, *args, **kwargs):
msg ={}
return Response(msg, status=status.HTTP_200_OK)
def get_access_token(self, username, password, client_id, client_secret, scope="read write"):
url = "http://127.0.0.1:80/o/token/"
payload = {
'grant_type': 'password',
'username': username,
'password': password,
'scope': scope
}
auth = HTTPBasicAuth(client_id, client_secret)
try:
response = requests.post(url, auth=auth, data=payload, verify=False, timeout=TIMEOUT)
except Exception as err:
print err