I set basic authentication in my setting.py as follows. Now I need a view that doesn't use basic authentication. How can I do it.
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',),
}
To exclude a view from authentication, set authentication_classes and permission_classes to [].
class SignupView(APIView):
authentication_classes = []
permission_classes = []
def post(self, request):
# view code
You simply need to set the authentication_classes on your view. Have a look at http://www.django-rest-framework.org/api-guide/authentication/#setting-the-authentication-scheme for an example.
Edit:
To remove authentication, set the authentication_classes to an empty list. Don't forget to remove permissions as well since they usually rely on authentication.
Related
How to handle complex required permissions in any API using django-rest-framework?
For example, you have three tier support operators who have access to APIs, but they should only have access to respective endpoint and as the last tier, superadmin should have everything in hands.
How to solve this simple problem by django group and permissions?
There are lots of answers being related to AND or OR the perms in permission_classes like
def get_permissions(self):
return (
IsAuthenticated & (IsCommitteeHead|IsCommitteeMember|IsAdminUser)
)()
or
permission_classes = [IsAuthenticated &(IsCommitteeHead|IsCommitteeMember|IsAdminUser)]
but I think hard coding always makes the code a complete mess!
Create new permission model permission from django base model permission like this:
from rest_framework.permissions import DjangoModelPermissions
class FullDjangoModelPermissions(DjangoModelPermissions):
perms_map = {
'GET': ['%(app_label)s.view_%(model_name)s'],
'OPTIONS': ['%(app_label)s.view_%(model_name)s'],
'HEAD': ['%(app_label)s.view_%(model_name)s'],
'POST': ['%(app_label)s.add_%(model_name)s'],
'PUT': ['%(app_label)s.change_%(model_name)s'],
'PATCH': ['%(app_label)s.change_%(model_name)s'],
'DELETE': ['%(app_label)s.delete_%(model_name)s'],
}
And in view class like this:
class SomeAwuful(GenericAPIView):
...
permission_classes = [FullDjangoModelPermissions]
...
Then you can go in Django admin dashboard and set who has access to what, or creating group to access features, like this:
I am managing my User Model (for customers), but i don't know how can i use simple-jwt for my Customer Model with it's custom Login View.
models.py
from django.db import models
class Customer(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(max_length=100)
password = models.CharField(max_length=100)
and also, i want to manage my customer session by saving the Refresh Token,
can anyone please tell me how can i achieve that.
After some research, I came to the conclusion that Simple JWT doesn't have any special support for user models that are not derived from AbstactUserModel.
It means if you are managing the Customer model, either you need to extend it from AbstactUserModel or you should use jwt instead of Simple jwt.
First install simple jwt with the command
pip install djangorestframework-simplejwt
You must then configure your django project to use the libary with following option in settings.py
REST_FRAMEWORK = {
...
'DEFAULT_AUTHENTICATION_CLASSES': (
...
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
...
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': True,
'UPDATE_LAST_LOGIN': False,
'ALGORITHM': 'HS256',
'SIGNING_KEY': settings.SECRET_KEY,
'VERIFYING_KEY': None,
'AUDIENCE': None,
'ISSUER': None,
'AUTH_HEADER_TYPES': ('Bearer',),
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
'JTI_CLAIM': 'jti',
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}
In your root urls.py add the following
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
...
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
...
]
Simple JWT by default only sends user id in the token. You can customize it further to send more information in your serializers.py by doing the following
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
"""Customizes JWT default Serializer to add more information about user"""
#classmethod
def get_token(cls, user):
token = super().get_token(user)
token['name'] = user.name
token['email'] = user.email
token['is_superuser'] = user.is_superuser
token['is_staff'] = user.is_staff
return token
Then in your views.py add the following
from users import serializers
class CustomTokenObtainPairView(TokenObtainPairView):
# Replace the serializer with your custom
serializer_class = serializers.CustomTokenObtainPairSerializer
You can read more here
I could fix this problem adding 'rest_framework_simplejwt' to INSTALLED_APPS after the app that has the custom user model.
in your views.py file, import this
from rest_framework_simplejwt.tokens import RefreshToken
next, create a refresh token in def post - the one you use for logging in
def post(self, request):
...
refresh = RefreshToken.for_user(user)
...
return the generated refresh token and access token in the response body
return Response(
{
'refresh': str(refresh),
'access': str(refresh.access_token),
},
status = status.HTTP_200_OK
)
What I have suggested is a simple and super basic implementation of what I believe you are looking for. I got it from here. But if you want a better and more customized, neater implementation, refer this article.
I'm using Django Rest Framework for created a API. In this project i want to capture parameters in the URL. For example i want to capture the username and password of a user and my idea is like this:
http://localhost:8000/accounts/login/?unsername=username&password=password
But i cant, I' usin routers and django-filter, but i cant get the parameters url. My project files are there:
view.py:
class AccountsData(viewsets.ModelViewSet):
queryset = models.UserData.objects.all()
serializer_class = serializers.AccountsDataSerializer
permission_classes = (IsAuthenticated,)
filter_backends = (filters.DjangoFilterBackend,)
filterset_fields = ['username', 'password']
lookup_url_kwarg = 'username'
#action(methods=['get'], detail=True, url_name='login', url_path='login')
def login(self, request, pk=None):
return Response({"Login successfully"}, 200)
urls.py:
from api import views
router = routers.SimpleRouter()
router.register(r'accounts', views.AccountsData)
Request query parameters have nothing to do with routing, they are passed with the request independently of how you configure the route. You have access to them in request.query_params, for example, request.query_params.get('username') would get the value of the username parameter.
Being said that, your idea has a terrible mistake: password or any kind of confidential data should NEVER go in query parameters, you should use an http verb that carries the data in its body (POST, for example).
I need to make view accessible without authentication, based on a variable passed in urls.py.
My idea is something like this:
urls.py
url(r'^oidc-api/', include('api.urls'), {'logged': True})
views.py
class ExampleViewSet(ModelViewSet):
if logged: # How can I get this variable, passed in urls.py?
permission_classes = () # This will exclude current view from authentication
queryset = Widget.objects.filter(visible=True)
serializer_class = ExampleSerializer
filter_backends = (DjangoFilterBackend,)
filter_fields = ('example_id',)
However, I can not access logged variable that is passed from urls.py.
John
You can't do that.
What you could do is, remove those permission classes from the views manually or set those to an empty set as,
class ExampleViewSet(ModelViewSet):
permission_classes = ()
i have this view handling only /GET/ request to display all authors only if the logged user is superuser
class AuthorView(generics.ListAPIView):
serializer_class = AuthorSerializer
queryset = Author.objects.all()
permission_class = (IsSuperUser,)
And the permission for superuser:
class IsSuperUser(permissions.BasePermission):
def has_permission(self, request, view):
user = request.user
return user.is_authenticated() and user.is_superuser
The permission does not seems to be working, placed the pdb in has_permission the control does not seems to coming there.
What am i missing ?
It should be:
permission_classes = (IsSuperUser,)
and not
permission_class = (IsSuperUser,)