Django REST Framework BasicAuthentication is not applied as default authentication class - django

I have a Django REST Framework project and I added
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
]
}
to settings.py and I expect BasicAuthentication is applied to all pages as default but still it does not require any authentication to display the content. that is weird. Do I have to do something I did not do?
urls.py:
urlpatterns = [
path('admin/', admin.site.urls),
path('student/', include('blogapp.urls')),
path('api/', include('api.urls')),
path('api-auth/', include('rest_framework.urls')),
]
setting.py:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'blogapp',
]
blog_app/urls:
urlpatterns = [
path('', StudentView.as_view()),
]
views.py:
class StudentView(generics.ListCreateAPIView):
queryset = Student.objects.all()
serializer_class = StudentSerializer
UPDATE 1:
Also per-view authentications not work!
UPDATE 2:
This is my project source code.

Authentication is not the same as permission. You'll also need to add a default permission class if you require all users to be authenticated (using one of the authentication methods you wish to use):
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
Also, make sure you're testing the right view (/api/list/). Your project (as you linked) has two StudentViews, one of which is a DRF view, the other (/student/) isn't. The latter will not be aware of DRF configuration.

Related

Getting "CSRF token missing or incorrect" on obtain token request

We are using Django REST Framework and we are using user logins. From a web client we have a login screen and use obtain_auth_token from the REST Framework to obtain an api token. The web client uses XMLHttpRequest.
It starts out with working fine. The web client obtains a token using username+password and uses that token in the following API calls.
When I return the next day and open a new browser tab and try to log in I get a 403 Forbidden and the Django logs (and the body reply) says {"detail":"CSRF Failed: CSRF token missing or incorrect."}
I can see that the incoming request has a csrftoken cookie and a sessionid cookie. I can see the same cookies if I use the browser "Developer Tools". If I remove those two cookies, it works fine afterwards.
Also, if I launch a private browser window (= incognito), the web app works fine.
I am do not know why those cookies appear, when they appear exactly and why the REST framework do not like them.
I have two suspicions:
We also use the Django admin interface. Could it be that the login to the admin interface on the same domain will plant those cookies and somehow interfere with the REST Framework?
Something about time passes will make the problem appear? It seems to me that the problem does not appear until "the day after" if I clear the cookies. This might very well be other circumstances tricking me, like point 1 above.
Any suggestions on how to resolve this?
For reference, some snippes of our Django setting.py:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'request_logging.middleware.LoggingMiddleware',
]
INSTALLED_APPS = [
'mybackend.apps.MybackendConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_cleanup.apps.CleanupConfig',
'rest_framework',
'rest_framework.authtoken',
'adminsortable',
'corsheaders',
'django_filters',
'storages',
]
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissions'
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
),
}
From urls.py:
from rest_framework.authtoken import views as restviews
...
urlpatterns = [
path('admin/', admin.site.urls),
url(r'^api/token-auth/obtain_auth_token', restviews.obtain_auth_token),
url(r'^api/', include(router.urls)),
]
Seems like the SessionAuthentication is the culprit. My guess is that is was added to be able to play with the REST interface from a browser for testing purposes.
So if I remove SessionAuthentication it seems to work.
Now the config looks like this:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissions'
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
# 'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
),
}

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://127.0.0.1:8000/api/task-list/

I'm working on a vuejs and django rest single page application.
the problem is so clear, that I'm getting the Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource error.
My vuex code be like:
mutations:{
addTask: function(){
axios({
url: 'http://127.0.0.1:8000/api/task-list/',
method: 'POST',
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
}).then(response => {
console.log(response.data);
}).catch(err => {
console.log(err.response);
})
}
},
and my django rest urls.py, in my django application urls:
urlpatterns = [
path('task-list/', TaskList.as_view()),
path('task-create/', TaskCreate.as_view())
]
and my main app urls:
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('task.urls')),
path('api/', include('authentication.urls')),
path('home/', returnHome)
]
my views.py code:
class TaskList(APIView):
def get(self, request):
tasks = Task.objects.all()
serialized = TaskSerializer(tasks, many=True)
return Response(serialized.data, status=200)
my vue app is running on http://localhost:8080, so I installed django cors headers, configured it like the below code:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# rest api
'rest_framework',
'rest_framework.authtoken',
'corsheaders',
# my apps
'authentication',
'task'
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
CORS_ALLOWED_ORIGINS = [
'http://localhost:8080',
'https://localhost:8080'
]
Although, I'm still getting the Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://127.0.0.1:8000/api/task-list/. (Reason: CORS request did not succeed) Error!
I even tried CORS_ALLOW_ALL_ORIGINS = True , but there are still no changes...
Is there something I'm doing wrong here? I searched a lot about this, but everywhere the solution was about to write the correct configuration for corsheaders.
You problem is the placement of the Django middleware, especially relatively to CommonMiddleware. It should be listed higher than it.
From django-cors-headers README:
CorsMiddleware should be placed as high as possible, especially before any middleware that can generate responses such as Django's CommonMiddleware or Whitenoise's WhiteNoiseMiddleware. If it is not before, it will not be able to add the CORS headers to these responses.
Also if you are using CORS_REPLACE_HTTPS_REFERER it should be placed before Django's CsrfViewMiddleware (see more below).

Credential error when trying to preserve data

I am developing an api in Django Rest Framework, which at the moment only registers new users, but I have a problem and that is that now I am adding a bit of security, which is being controlled by means of tokens, but at the time of entering the token of an authenticated user for the creation of users generates an error of The authentication credentials were not provided, but I send the token as follows:
This is plugin rest client visual studio code
My authentication:
### Login user
POST http://localhost:8000/auth-token/
Content-Type: application/json
{
"username": "hamel",
"password": "contraseña"
}
This return a token b6773c67ecb940ae4fb7c9d49466a01fd46f5eb4
My register of user:
### Create User
POST http://localhost:8000/api/v1/users
Authorization: Token b6773c67ecb940ae4fb7c9d49466a01fd46f5eb4
Content-Type: application/json
{
"first_name": "Carlos",
"last_name": "Carlos",
"username": "carlos",
"email": "correo#rgrgr.com",
"password": "contraseña",
"password2": "contraseña"
}
My setting.py:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
]
}
This my views.py:
class CreateUser(APIView):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
def post(self, request, format=None):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
This is my INSTALLED_APPS:
INSTALLED_APPS = [
'users',
'profiles',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework.authtoken',
'corsheaders',
]
This is my MIDDLEWARE:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
This my urls main:
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from users.views import CustomToken
urlpatterns = [
path('auth-token/', CustomToken.as_view()),
path('api/v1/', include('users.urls')),
path('admin/', admin.site.urls),
] + static(
settings.MEDIA_URL, document_root=settings.MEDIA_ROOT,
)
This my urls app users:
from django.urls import path
from . import views
urlpatterns = [
path('users', views.CreateUser.as_view()),
]

same token is getting on token request in django

Hi I am using django rest-framework, i want to implement token base authentication,
i am using basic rest-framework token authentication module.
but it return same token on every request.
ex(87d97bb2df56e39c12b38131087bcfd232720d9a), i am getting this string on every request i sent to my server.
my setting.py file
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'restApp2', # Local Apps (My project's apps)
'rest_framework',
'rest_framework.authtoken',
'rest_auth',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication', # <-- And here
],
}
urls.py file
from django.contrib import admin
from django.urls import path, include
from restApp2 import views
from rest_framework.authtoken.views import obtain_auth_token
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', views.HelloView.as_view(), name='hello'),
path('api-token-auth/', obtain_auth_token, name='api_token_auth'), # <-- And here
]
urlpatterns += [
path('accounts/', include('django.contrib.auth.urls')),
]
i am calling bellow url using post method from POSTMON.
POST http://localhost:7070/rest-auth/login/
and in response i get
87d97bb2df56e39c12b38131087bcfd232720d9a.
but i want different token on new request.
please help me, Thank You
If you check obtain_auth_token view, its either getting existing token or creating new one if there is no token in the database for the user.
If want new token on each login, then delete the previous tokens after logout.
django rest framework - token authentication logout

Django rest-auth registration. How to return user_id with the key when using token authentication

I am using Djando rest_auth.registration.
My corresponding entry in urls.py is
url(r'^rest-auth/registration/', include('rest_auth.registration.urls'))
My authentication class is rest_framework.authentication.TokenAuthentication
This rest API call works perfectly well.
When I register via this API I get the below response.
{
"key": "3735f13cd69051579156f98ffda338a2d7a89bb5"
}
I also want to include the user_id field in the response. How do I go about doing that. I tried extending the method get_response_data from class RegisterView(CreateAPIView): but unable to do so. Can someone please advise the best practice to achieve this. Code would be ideal. Thanks.
I want to use the rest-auth/registration/ url provided out of box by rest_auth.registration. I do not want to create a separate new URL for this.
My Settings.py as follows
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'sdAPI.apps.SdapiConfig',
'rest_framework',
'rest_framework.authtoken',
'rest_auth',
'rest_framework_swagger',
'rest_auth.registration',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.facebook',
'allauth.socialaccount.providers.google',
'django_extensions',
]
# auth and allauth settings
LOGIN_REDIRECT_URL = '/'
SOCIALACCOUNT_QUERY_EMAIL = True
SOCIALACCOUNT_PROVIDERS = {
'facebook': {
'SCOPE': ['email', 'publish_stream'],
'METHOD': 'oauth2' # instead of 'oauth2'
}
}
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
)
}
SITE_ID = 1
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
REST_SESSION_LOGIN = False
My urls.py as follows
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^user/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),
url(r'^rest-auth/', include('rest_auth.urls')),
url(r'^rest-auth/registration/',include('rest_auth.registration.urls')),
]
I think you only need to override the TOKEN_SERIALIZER option in your REST_AUTH_SERIALIZERS configuration.
from rest_framework.authtoken.models import Token
class TokenSerializer(serializers.ModelSerializer):
class Meta:
model = Token
fields = ('key', 'user')
Then, set it in your settings.py as shown in the docs,
REST_AUTH_SERIALIZERS = {
'LOGIN_SERIALIZER': 'path.to.custom.LoginSerializer',
'TOKEN_SERIALIZER': 'path.to.custom.TokenSerializer',
...
}