I've created a view for getting details of the user's profile.
user_views.py
#api_view(['GET'])
#permission_classes([IsAuthenticated])
def getUserProfile(request):
user = request.user
serializer = UserSerializer(user, many=False)
return Response(serializer.data)
urls.py
urlpatterns = [
path("/users/profile/", uv.getUserProfile, name="get-user-profile")
]
serializers.py
class UserSerializer(serializers.ModelSerializer):
name = serializers.SerializerMethodField(read_only=True)
isAdmin = serializers.SerializerMethodField(read_only=True)
class Meta:
model = User
fields = ['id', 'username', 'email', 'name', 'isAdmin']
def get_id(self, obj):
return obj.id
def get_isAdmin(self, obj):
return obj.is_staff
def get_name(self, obj):
name = obj.first_name
if name == '':
name = obj.email
return name
class UserSerializerWithToken(UserSerializer):
token = serializers.SerializerMethodField(read_only=True)
class Meta:
model = User
fields = ['id', 'username', 'email', 'name', 'isAdmin', 'token']
def get_token(self, obj):
token = RefreshToken.for_user(obj)
return str(token.access_token)
I'm sending a get request through post man and sending a authorization header with Bearer <token>. And got
{
"detail": "Authentication details were not provided."
}
Using django-rest-framework and django-rest-framework-simplejwt.
Figured it out like after a bit. Needed to add
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
}
to settings.py
Related
how to change permissions for current view overriding the DEFAULT_PERMISSION_CLASSES in django rest-framework
Here is how i set my defaultpermissions in my settings.py :
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication', # <-- And here
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
and i need to use AllowAny on the signUp method :
#permission_classes([AllowAny,])
#api_view(["POST", ])
def add_new_user(request):
if request.method == "POST":
lang = request.data["lang"]
..........
.........
.......
Still, it returns Authentication credentials were not provided. .. I mainly need to have permissions with a token with every request but not the register and login request. how to do it ??
A Way to do that is using Object Level Permissions in Django.
You just setup as normally in settings.py and add manually a permission into every class view.
For me is the best way to do it. Normally will be Views witch is are Admin only, Authenticated or just Open.
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoObjectPermissions',#Object Level Permission
]
}
After set this line into your settings.py just follow adding a permission_classes into view. Like:
class LoginUser(APIView):
permission_classes = [AllowAny, ]
...
References
DjangoObjectPermissions
Django Class Based Views
Here is how I solved this :
in my settings.py i added both permissions classes
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication', # <-- And here
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated', #both are mentioned
'rest_framework.permissions.AllowAny',
]
}
and in my view, I had to move the permission dictator to be the last thing before the view itself.
#api_view(["POST", ])
#permission_classes([AllowAny])
def login_user(request):
if request.method == "POST":
lang = request.data["lang"]
...
I'm trying to retrieve a token for the user using the following request through Postman.
http://127.0.0.1:8000/api-token-auth/
JSON Body -
{
"username": "user1",
"password": "testpass"
}
The following is the error response -
{
"detail": "CSRF Failed: CSRF token missing or incorrect."
}
I've checked the instructions provided in the official DRF Authentication document as well as various other question posts and implemented the following code.
settings.py
INSTALLED_APPS = [
...
'rest_framework',
'rest_framework.authtoken',
'allauth',
'allauth.account',
'allauth.socialaccount',
'rest_auth',
'rest_auth.registration',
....
]
AUTH_USER_MODEL = 'users.CustomUser'
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
signals.py
#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)
urls.py
from django.contrib import admin
from django.urls import include, path, re_path
from django_registration.backends.one_step.views import RegistrationView
from rest_framework.authtoken import views as authtoken_views
urlpatterns= [
path('admin/', admin.site.urls),
path("accounts/",
include("django_registration.backends.one_step.urls")),
path("accounts/",
include("django.contrib.auth.urls")),
path("api-auth/",
include("rest_framework.urls")),
path("api-token-auth/", authtoken_views.obtain_auth_token, name="api-token-auth"),
path("api/rest-auth/",
include("rest_auth.urls")),
path("api/rest-auth/registration/",
include("rest_auth.registration.urls")),
]
Have I missed something?
Found the issue.
The issue was not with the implementation, rather it was with Postman. Postman interceptor had retrieved cookies from the browser and had stored the CSRF Token with it. This token was automatically added to the request headers and hence, django tried to authenticate this request from Session Authentication which naturally should fail.
The solution-
Open the Postman cookies and Delete the CSRF Token.
PS- A curl request can always help in verifying such issues
So the problem I have already mentioned. I am a beginner, I might be doing some silly mistakes. So humble request to you guys to address my mistake and help me to complete my project. Thanks you all in advance.
setting.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticatedOrReadOnly',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
JWT_AUTH = {
'JWT_ALLOW_REFRESH': True,
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=3600),
}
this is the setting.py file and here I mention the required file
view.py
class LoginViewSet(viewsets.ViewSet):
""" Check email and password and return auth token. """
serializer_class = AuthTokenSerializer
authentication_classes((SessionAuthentication, TokenAuthentication, BasicAuthentication))
permission_classes((IsAuthenticated,))
def create(self, request):
""" Use ObtainAuthToken APIView to validate and create a token. """
return ObtainAuthToken().post(request)
this is the view.py file.
urls.py
router.register('login', views.LoginViewSet, base_name="login")
urlpatterns = [
path('', include(router.urls)),
path('login/', ObtainAuthToken.as_view()),
path(r'api-token-auth/', obtain_jwt_token),
path(r'api-token-refresh/', refresh_jwt_token),
]
Error Message
error
you must define http_method_names in DRF and specify your method access in your api.
class IndexViewAPI(generics.GenericAPIView):
http_method_names = ['get', 'head']
# some statements
I Have integrated the OAuth2.0 with django-rest-framework. When I send the authenticated request to my class based view I got this
{
"detail": "You do not have permission to perform this action."
}
settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
views.py
from rest_framework import permissions
from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope
class LogoutView(APIView):
"""
This will help in logout of user.
"""
authentication_classes = ()
permission_classes = (permissions.IsAuthenticated, TokenHasReadWriteScope)
def get(self, request):
return Response({'s': 'd'})
urls.py
from django.urls import path, re_path
from accounts.views import SignUpView, LoginView, LogoutView
urlpatterns = [
path('signup/', SignUpView.as_view()),
path('login/', LoginView.as_view()),
path('logout/', LogoutView.as_view()),
]
And this is what my headers look like
Content-Type:application/json
Authorization:Bearer 4A7qGgmHpbEWlJn5w4wCwxJ9jWfTZ5
This is the access token that I generated.
Make sure you have the following in your settings.py
AUTHENTICATION_BACKENDS = (
'oauth2_provider.backends.OAuth2Backend',
'django.contrib.auth.backends.ModelBackend'
)
And:
OAUTH2_PROVIDER = {
'REFRESH_TOKEN_EXPIRE_SECONDS': 360000,
'SCOPES': {'read': 'Read scope', 'write': 'Write scope', 'groups': 'Access to your groups'},
'ACCESS_TOKEN_EXPIRE_SECONDS': 1800
}
For debugging purposes:
Remove authentication_classes = () from view.py
Remove TokenHasReadWriteScope from view.py
If you want to make a logout endpoint, I would recommend using oauth2_views in your urls.py:
from oauth2_provider import views as oauth2_views
#.....
urlpatterns = [
#....
url(r'^logout/$', oauth2_views.RevokeTokenView.as_view()),
]
Got a weird scenario. I am on the Django Rest browser api with a logged in user.
When I update it is okay. But when I try to create a user, this error shows:
CSRF Failed: CSRF token missing or incorrect.
it also auto logged out me every single time.
In views.py, I already have added
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
Still same error and scenario.
In my settings.py:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
],
}
Anyone experienced this?