How to get and delete access token django api - django-rest-framework

I want to get access token and delete it in logout api.But i am unable to get access token for the current log in user.
models.py
class MyUserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError('Users must have an email address')
account = self.model(
email=self.normalize_email(email),
)
account.account_type = extra_fields.get('account_type')
account.set_password(password)
account.save(using=self._db)
return account
def create_superuser(self, email, password, **extra_fields):
account = self.create_user(
email,
password=password,
)
account.account_type = 'A'
account.is_admin = True
account.save(using=self._db)
return account
class Account(AbstractBaseUser):
type_choice = (
('A', 'Admin'),
('S','Student'),
('T','Teacher'),
)
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
account_type = models.CharField(choices=type_choice, max_length=1, null=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
#property
def is_staff(self):
return self.is_admin
#views.py
class AccountViewSet(viewsets.ViewSet):
def create(self,request):
# permission_classes = [TokenHasReadWriteScope]
try:
email=request.data.get('email')
password=request.data.get('password')
print(request.data)
# account_type=request.data.get('account_type')
if not all([email,password]):
raise Exception('All Fields are mandatory')
obj=Account()
obj.email=email
obj.set_password(password)
obj.save()
Application.objects.get_or_create(user=obj, client_type=Application.CLIENT_CONFIDENTIAL,
authorization_grant_type=Application.GRANT_PASSWORD)
token = get_access_token(obj)
return Response({"response":token, "success": True}, status=status.HTTP_200_OK)
except Exception as error:
traceback.print_exc()
return Response({"message": str(error), "success": False}, status=status.HTTP_200_OK)
def list(self,request):
try:
user=Account.objects.all()
users=[]
for i in user:
users.append({
"name":i.name,
"Address":i.Address,
"account_type":i.account_type,
})
return Response({"success":True, "users":users})
except Exception as error:
traceback.print_exc()
return Response({"message": str(error), "success": False}, status=status.HTTP_200_OK)
def retrieve(self, request, pk=None):
user = Account.objects.get(id=pk)
data = {
"name":user.name,
"email":user.Address,
#"password" : user.password,
#"date_of_birth":user.date_of_birth,
"account_type":user.account_type
}
return Response({"data":data,"success":True})
def destroy(self, request, pk=None):
employee = Account.objects.get(id=pk).delete()
print('>>>>>>>>>>',employee)
#employee.delete()
return Response({"success":'done',"message":"delete called"})
class LoginViewSet(viewsets.ViewSet):
def create(self,request):
try:
email = request.data.get('email')
password = request.data.get('password')
print(email,password)
if not all([email,password]):
raise Exception('all fields are mandatory')
acc = Account.objects.get(email = email)
print(acc.check_password(password))
account = authenticate(username=email,password=password)
print(account)
if account is not None:
token = get_access_token(account)
obj = Account.objects.get(email=account)
data = {
"email":account.email,
}
else:
raise Exception('Credential not matched')
return Response({"message": "Login Successfully", "user_info": data, "token": token, "Success": True}, status = status.HTTP_200_OK)
except Exception as error:
traceback.print_exc()
return Response({"message":str(error),"success":False},status = status.HTTP_200_OK)
class LogoutViewSet(viewsets.ViewSet):
def list(self, request, format=None):
accesstoken=AccessToken.objects.get(token=request.META.get('HTTP_AUTHORIZATION'))
return Response('response',status=status.HTTP_200_OK)

Related

Swagger - add manual parameters?

Very new to swagger
class VerifyEmailAPI(generics.GenericAPIView):
"""
Verify Email of a registered user
"""
token_param_config = openapi.Schema(type=openapi.TYPE_OBJECT, properties={
'token': openapi.Schema(type=openapi.TYPE_STRING, description='Test')
})
#swagger_auto_schema(manual_parameters=[token_param_config])
def get(self, request):
token = request.GET.get('token')
# print(token)
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
# print(payload)
user = User.objects.get(id=payload['user_id'])
# print(user)
if not user.is_verified:
user.is_verified = True
user.save()
return Response({'msg': 'We have verified your email.'})
except jwt.ExpiredSignatureError as identifier:
return Response({'msg': 'Link has expired.'})
except jwt.exceptions.DecodeError as identifier:
return Response({'msg': 'Please request a new link, this one is not working.'})
I am getting: > AttributeError: object of class Schema has no attribute in_
I tried:
1)
#swagger_auto_schema(request_body=openapi.Schema(type=openapi.TYPE_OBJECT, properties={
'token': openapi.Schema(type=openapi.TYPE_STRING, description='Test')
}))
#swagger_auto_schema(method='get', request_body=openapi.Schema(type=openapi.TYPE_OBJECT, properties={
'token': openapi.Schema(type=openapi.TYPE_STRING, description='Test')
}))
token_param_config = openapi.Parameter('token', in_=openapi.IN_QUERY,
description='A system generated token to verify the email', type=openapi.TYPE_STRING)
#swagger_auto_schema(manual_parameters=[token_param_config])
Not sure where I am going wrong with this.

(Django Simple JWT) 401 Unauthorized when logging out

I'm having trouble with simple JWT when I try to log out. I'm informed that when logging out, the cookie must be deleted and the refresh token must be blacklisted!
All of the previous authentication steps (register, login) worked as expected, except for logout.
Register
Login
Logout
In the capture above I got 401 unauthorized. The cookie seemed to be removed as intended.
As suggested by the Q/As I found, I have tried the following:
Print Exception but nothing showed beside 401 error.
Add authorization header and interchange between 'Bearer ' and 'JWT '.
Modify settings.py and apply simple jwt authentication code templates. My code is as followed:
settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
'ALGORITHM': 'HS256',
'SIGNING_KEY': SECRET_KEY,
'VERIFYING_KEY': None,
'AUTH_HEADER_TYPES': ('Bearer', 'JWT',),
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'USER_ID_FIELD': 'email',
'USER_ID_CLAIM': 'user_id',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
}
AUTH_USER_MODEL = 'users.CustomUser'
CORS_ALLOWED_ORIGINS = [
"http://127.0.0.1:3000",
"http://localhost:3000",
"http://127.0.0.1:8000",
"http://localhost:8000",
]
serializers.py
class LogoutSerializer(serializers.Serializer):
refresh = serializers.CharField()
default_error_messages = {
'bad_token': _('Token is invalid or expired')
}
def validate(self, attrs):
self.token = attrs['refresh']
return attrs
def save(self, **kwargs):
try:
RefreshToken(self.token).blacklist()
except TokenError:
self.fail('bad_token')
except Exception as e:
print('\nException in logging out:', e)
views.py
class RegisterView(APIView):
permission_classes = [AllowAny]
def post(self, request, format='json'):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
if user:
json = serializer.data
return Response(json, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class LoginView(APIView):
def post(self, request):
email = request.data['email']
password = request.data['password']
user = CustomUser.objects.filter(email=email).first()
if user is None:
raise AuthenticationFailed('User not found!')
if not user.check_password(password):
raise AuthenticationFailed('Incorrect password!')
payload = {
# 'id': user.id,
'email': user.email,
'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=60),
'iat': datetime.datetime.utcnow()
}
token = jwt.encode(payload, 'secret', algorithm='HS256')
response = Response({'message': 'success'})
response.set_cookie(key='jwt', value=token, httponly=True)
response.data = {
'jwt': token
}
return response
class LogoutView(generics.GenericAPIView):
serializer_class = LogoutSerializer
permission_classes = (permissions.IsAuthenticated,)
def post(self, request):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(status=status.HTTP_204_NO_CONTENT)
users/urls.py
urlpatterns = [
path('', UserList.as_view()),
path('register', RegisterView.as_view()),
path('login', LoginView.as_view()),
path('user', UserView.as_view()),
path('logout', LogoutView.as_view()),
]
models.py
class CustomUserManager(BaseUserManager):
def create_superuser(self, email, password=None):
if password is None:
raise TypeError('Password should not be none')
user = self.create_user(email, password)
user.is_superuser = True
user.is_staff = True
if user.is_superuser is not True:
raise ValueError(
'Superuser must be assigned to is_staff=True.')
if user.is_staff is not True:
raise ValueError(
'Superuser must be assigned to is_superuser=True.')
user.save()
return user
def create_user(self, email, password=None):
if email is None:
raise TypeError('Users should have a Email')
email = self.normalize_email(email)
user = self.model(email=email)
user.set_password(password)
user.save()
return user
AUTH_PROVIDERS = {'facebook': 'facebook', 'google': 'google',
'twitter': 'twitter', 'email': 'email'}
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=255, unique=True, db_index=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
about = models.TextField(_(
'about'), max_length=500, blank=True)
auth_provider = models.CharField(
max_length=255, blank=False,
null=False, default=AUTH_PROVIDERS.get('email'))
USERNAME_FIELD = 'email'
# REQUIRED_FIELDS = ['username']
objects = CustomUserManager()
def __str__(self):
return self.email
def tokens(self):
refresh = RefreshToken.for_user(self)
return {
'refresh': str(refresh),
'access': str(refresh.access_token)
}
The code above was derived from several tutorials but somehow did not work like they should!
Could you suggest me a way to solve this? Thank you!
This is because you have permission_classes = (permissions.IsAuthenticated,) in the LogoutView.
You can safely allow logout for any user.
permission_classes = (AllowAny,)

Testing POST with authentication in Django Rest Framework issue 401 returing

I'm trying to test POSTing data to a view in django-rest-framework that requires authentication. But I can't. I've read many threads of supposed solutions, but can't find any that solves to me.
Test:
class TodoListCreateAPIViewTestCase(APITestCase):
url = reverse("todolist:add")
def setUp(self):
self.username = "john"
self.email = "john#snow.com"
self.password = "you_know_nothing"
self.user = User.objects.create_user(self.username, self.email, self.password)
self.token = Token.objects.create(user=self.user)
#checking token here
def test_create_todo(self):
self.client.login(email=self.email, password='you_know_nothing')
client = APIClient()
client.credentials(HTTP_AUTHORIZATION='Token ' + self.token.key)
response = self.client.post(self.url, {"list_name": "Clean the room!"}, format='json')
self.assertEqual(201, response.status_code)
View
class Addtodolist(APIView):
authentication_classes = (JSONWebTokenAuthentication,TokenAuthentication)
permission_classes = [IsAuthenticated, ]
def post(self, request):
data = request.data
todolist_instance = Todolist.objects.filter(for_user=self.request.user).first()
if not todolist_instance:
list_serilaizer = AddtodolistSerializers(data=data, context={'user': request.user})
if list_serilaizer.is_valid():
list_serilaizer.save()
return Response(data=success_response(data=list_serilaizer.data, msg='Successfully Created list!'),
status=status.HTTP_200_OK)
else:
return Response(
failure_response(data={'detail': list_serilaizer.errors()}, msg='Following errors occured'),
status=status.HTTP_400_BAD_REQUEST)
else:
return Response(
failure_response(data={'detail': 'User can have only 1 List'}, msg='User can have only 1 List'),
status=status.HTTP_409_CONFLICT)
Change your code like this:
from django.shortcuts import reverse
from django.contrib.auth import get_user_model
from rest_framework.test import APIClient, APITestCase
from rest_framework.authtoken.models import Token
class TodoListCreateAPIViewTestCase(APITestCase):
url = reverse("todolist:add")
def setUp(self):
self.username = "john"
self.email = "john#snow.com"
self.password = "you_know_nothing"
self.user = get_user_model().objects.create_user(self.username,
self.email,
self.password)
self.token = Token.objects.create(user=self.user)
def test_create_todo(self):
client = APIClient()
client.login(username=self.username,
email=self.email,
password=self.password)
client.credentials(HTTP_AUTHORIZATION='Token ' + self.token.key)
response = client.post(self.url,
{"list_name": "Clean the room!"},
format='json')
self.assertEqual(response.status_code, 201)

Tocken authentication fails in django rest

I can create user models. But authentication always fails even if there exists such a user with the given credentials
models.py have user creation method as
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
views.py have login/authentication method as
class ObtainAuthToken(APIView):
#csrf_exempt
def post(self, request):
user = authenticate(
username=request.data['username'],
password=request.data['password'])
if user:
token, created = Token.objects.get_or_create(user=user)
return Response({'token': token.key, 'user': UserSerializer(user).data})
return Response('Invalid username or passwordee', status=status.HTTP_400_BAD_REQUEST)
in settings.py
AUTH_USER_MODEL = 'account.User'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
settings.py is here
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
}
What is the problem with this code?

Django LoginView() return a Nonetype

This is views:
class LoginView(View):
def get(self,request):
return render(request,'login.html',{})
def post(self,request):
login_form = LoginForm(request.POST)
if login_form.is_valid():
user_name = request.POST.get("username", '')
pass_word = request.POST.get("password", '')
user = authenticate(username=user_name, password=pass_word)
if user is not None:
login(request, user)
return render(request, 'index.html')
else:
return render(request, 'login.html', {"msg": "User name or password error!"})
This is forms:
class LoginForm(forms.Form):
username = forms.CharField(required=True)
password = forms.CharField(required=True, min_length=5)
Here is the login verification why login_form return a NoneType,I return an NoneType whether I login to submit any parameter._bound_fields_cache is None,_errors is None.So what should I write?

Resources