1

I have a simple function-based @api_view(['POST']) with @permission_classes([AllowAny]) and DRF settings in settings.py are:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
}

The documentation says:

The AllowAny permission class will allow unrestricted access, regardless of if the request was authenticated or unauthenticated.

But I'm getting the following response on making a post request:

{
    "detail": "Authentication credentials were not provided."
}

What might be the problem? Do I have to modify DEFAULT_AUTHENTICATION_CLASSES from the settings? I don't want the permissions to be required while making the request on this @api_view:

@api_view(['POST'])
@permission_classes([AllowAny]) 
def reset_password_request(email):
    try:
    #...

accounts/urls.py:

urlpatterns = [
    path('user/<str:pk>/', views.getUserById, name='user'),
    path('user/password_reset_request/',
         views.resetPasswordRequest, name='password_reset_request'),
]
aaron
  • 39,695
  • 6
  • 46
  • 102
Faisal Nazik
  • 2,367
  • 4
  • 17
  • 40
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/241871/discussion-between-faisal-nazik-and-aaron). – Faisal Nazik Feb 09 '22 at 15:35

3 Answers3

2

If DEFAULT_PERMISSION_CLASSES is not specified, it defaults to allowing unrestricted access.

The problem is in your URL patterns, where password_reset_request satisfies <str:pk> and getUserById with @permission_classes([...]) is called instead.

Either use the uuid path converter:

urlpatterns = [
    # path('user/<str:pk>/', views.getUserById, name='user'),  # Change this
    path('user/<uuid:pk>/', views.getUserById, name='user'),   # to this
    path('user/password_reset_request/',
         views.resetPasswordRequest, name='password_reset_request'),
]

Or reorder to match password_reset_request first:

urlpatterns = [
    # path('user/<str:pk>/', views.getUserById, name='user'),  # Move this
    path('user/password_reset_request/',
         views.resetPasswordRequest, name='password_reset_request'),
    path('user/<str:pk>/', views.getUserById, name='user'),    # to here
]

References:

aaron
  • 39,695
  • 6
  • 46
  • 102
0

According to this, the position of decorator is wrong. The first decorator to be executed should be on the top. Change your decorator to the bottom like this:

@api_view(['POST'])
@permission_classes([AllowAny])
def reset_password_request(email):
    try:
    #...

Check out the official documentation for reference.

Siva Sankar
  • 1,672
  • 1
  • 9
  • 16
  • I tried as you suggested, the same thing happened, is there any issue from `'rest_framework_simplejwt.authentication.JWTAuthentication'`, Can we swap this and same time use JWT. – Faisal Nazik Feb 09 '22 at 06:44
  • As far as I know AllowAny is regarding the permission classes. It has nothing to do with the authentication classes. It has to work for either user is authenticated or not. I am not sure. Please check once again if there is something (jwt middleware or drf) in settings.py that is restricting this – Siva Sankar Feb 09 '22 at 07:55
0

Let's work through it step by step: Add DEFAULT_PERMISSION_CLASSES as follows (for troubleshooting):

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
     )
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
}

** EDIT 1 **

Try adding rest_framework.authentication.SessionAuthentication as follows:

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
     )
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
        'rest_framework.authentication.SessionAuthentication'
    ],
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
}

** EDIT 2 **

Now that you have a 403, modify the default to rest_framework.permissions.AllowAny as shown below. If this works, remove the DEFAULT_PERMISSION_CLASSES and use decorators instead.

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.AllowAny',
     )
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
        'rest_framework.authentication.SessionAuthentication'
    ],
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
}
sitWolf
  • 930
  • 10
  • 16
  • Doing this undermines other classes , Like DEFAULT_SCHEMA_CLASS , like http://localhost:8000/api/v1/docs/ Here anyone can access the docs of the API but now this also says `Authentication credentials were not provided.` on this endpoint. – Faisal Nazik Feb 09 '22 at 10:46
  • previously it was giving an error with status code 401 means forbidden like in my original settings, but now giving 403 meaning unauthorized, but not allowing the request. – Faisal Nazik Feb 09 '22 at 11:14
  • Have you been able to test the latest edit? How did it work for you? – sitWolf Feb 09 '22 at 13:42
  • Yes. Same problem – Faisal Nazik Feb 09 '22 at 14:03
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/241868/discussion-between-faisal-nazik-and-scriptcode). – Faisal Nazik Feb 09 '22 at 14:49