Using Django admin application AND disabling session middleware? - django

I am building a django server for an API that relies on JWT (or Token based - https://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication) authentication for our users.
I don't need session based authentication for any purpose. It creates an unnecessary query on each request, and also authenticates users when I don't want to authenticate them (I want browsers to only authenticate when it includes an Authentication header in the request, and stay AnnonymousUser otherwise. This is because it creates issues in some of my middlewares where I verify if I am dealing with a guest or a authenticated user).
However, the issue comes when I try to use the admin application as well (I can't imagine building this app without the use of the django admin page). When I remove the session-related middlewares:(django.contrib.sessions.middleware.SessionMiddleware, django.contrib.auth.middleware.AuthenticationMiddleware and django.contrib.messages.middleware.MessageMiddleware) from my settings file, I get the following error when I do a runserver:
ERRORS:
?: (admin.E408) 'django.contrib.auth.middleware.AuthenticationMiddleware' must be in MIDDLEWARE in order to use the admin application.
?: (admin.E409) 'django.contrib.messages.middleware.MessageMiddleware' must be in MIDDLEWARE in order to use the admin application.
?: (admin.E410) 'django.contrib.sessions.middleware.SessionMiddleware' must be in MIDDLEWARE in order to use the admin application.
Can someone think of a workaround where I can disable sessions in Django, while also being able to use the admin panel? One solution I thought of is to hack up adding the authorization header to each admin page request, but 1) I have no idea how to proceed with this idea and 2) (more importantly), I cannot do a runserver while disabling the session middlewares.

Related

Using a django app as a central authentication system to other django apps

(I am relatively new to Django, so sorry if I was misunderstanding anything ^^")
so let say I have app1 and app2, and I want to implement the same groups, roles and permission through these two apps by only having one database.
my idea was to create a central back end server that the two app authenticate through and grabs the roles from it. essentially this can be used for SSO(Single sign on) later. but now the target is to authenticate the user logging through one app and get his roles and groups from there.
In Django documentation I found "Authentication using REMOTE_USER":
which should allow me to do remote authentication (which is my target), was able to make it run but how am I supposed to give it the link of the Django authentication server.
my understanding is that after setting this remote user authentication, all groups, roles and permission checks doesn't need to be changed since Django should have access to the remote server that it authenticates through.
I hope that I wasn't misunderstanding "Authentication using REMOTE_USER" concept.
also if there is any other ideas on how to implement this, please let me know.
Thank you !
Sounds like REMOTE_USER is NOT what you're expecting it to be: when Django is configured to use this functionality, it foregoes Django's typical security, because it expects a web server situated in front of Django (e.g. APACHE or NGINX) to do user authorization on its behalf. In a nutshell, the web server passes along the user's id in every request it sends to Django in the REMOTE_USER header.
You expectations, on the other hand, seem directed at configuring a common Django app to authorize and authenticate users for other apps. This is a common configuration, and is effected by several steps, including these three:
(1) Adding to the common app's settings.py the other apps in the INSTALLED_APPS list. For example:
INSTALLED_APPS = [
...
'app1',
'app2',
]
(2) Include the apps URLconf in common api urls.py, for example:
path('app1/', include('app1.urls')),
path('polls/', include('app2.urls')),
(3) Run python manage.py migrate in order to create the database tables for two apps.
You'll probably have to fuss with your urls in the common app more that what I've sketched out above; and you might add a middleware to prevent unauthorized requests any access until authenticated.

Authenticating Access to Django Rest Framework using custom authentication from a Django App

Ive implemented a custom auth system in one(only) Django app on my project
Now I want to open my site up to Api access, is there a way to only let users from the Django app access this api. As I don't want to repeat myself (DRY) so was asking if it was possible to work backwards rather than to overwrite the Django rest Authentication with very similar code
DRF's SessionAuthentication is included in the default DRF settings and is entirely transparent to users who are already familiar with logging in to your site. You can add it to the list of authenticators for DRF:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
# ...
'rest_framework.authentication.SessionAuthentication',
)
}
The session a user establishes when logging in to your site now also authenticates them for DRF's browsable API and any API calls.
More info: https://www.django-rest-framework.org/api-guide/authentication/#sessionauthentication
If you're instead asking how to do something like issue API keys, DRF's TokenAuthentication can do that for you. You'll just need to add a view to your site that allows users to retrieve their generated tokens.
More info: https://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication

Using Django Rest Framework for only certain apps inside Django Application

I'm not sure if this is possible since an extensive search gave me nothing. Or I might be searching the wrong terms.
Now I have a few apps inside my Django application as follows:
--AppOne
--AppTwo
--ExtendedAdmin
manage.py
Now, AppOne and AppTwo use Django Rest Framework and its related Token Auth Mechanism. For the extendedAdmin, I'd like to use native Django Auth or even SessionAuth of DRF since I'm trying to add quite an extensive admin panel to the application. I've not been able to find a satisfactory way of customizing Django Rest Framework to work it's auth mechanisms only for certain applications. Is there a way to do this? If not, what should I be doing different?
So far, I know you cannot. Because django rest framework intercepts the url and then performs its own logic of token validation. But there are solutions that you can use to keep both Session and Token Authentication.
I am using this for all my projects -
I keep Session Authentication for all urls that will be accessed for normal browsing
and I use api urls with django rest framework to be prefixed with /api for my api urls
For example -
The Session Based login is at http://<host>/account/login
and TokenBased login is at http://<host>/api/account/login
The easiest way to make prefixed url for django rest framework is by using Routers - http://www.django-rest-framework.org/api-guide/routers/#defaultrouter
Example -
class UserViewSet(ModelViewSet): # just a sample view set
...
router = routers.SimpleRouter()
router.register(r'api/users', UserViewSet)

Django Admin - Re-authentication?

I'm in a bit of a dilemma at the moment regarding Django's admin backend. The default authentication system allows already logged-in users that have staff privileges to access the admin site, however it just lets them straight in.
This doesn't feel “right” to me, and I'm wondering if it would be difficult to at least require a re-authentication of that same session in order to get into the backend.
Preferably though, it'd be good if the frontend sessions could be separated from the backend ones (though still using the same user objects), this would allow a clean separation of both parts of the site. Would this perhaps require two separate authentication backends? Would something like this be difficult to achieve?
Here's an idea: run the admin app on a different domain to the frontend. The cookies won't be valid in the other domain, so the user will have to log in again. All you'd need would be a separate Apache vhost and a basic settings.py that just has contrib.admin in INSTALLED_APPS.
You could probably implement a middleware that asks for authentication when accessing the admin site from a referer not in the admin site. It could log the person out and make them log back in, but even that wouldn't be necessary. Just require another password entry, and redirect them if it fails. It might involve setting a session variable, is_admin_authenticated or something.

Different authentication backend for the django admin

What would be the best solution to use a different authentication backend for the Django admin site?
See the documentation, which contains this quote:
The Django admin system is tightly
coupled to the Django User object
described at the beginning of this
document. For now, the best way to
deal with this is to create a Django
User object for each user that exists
for your backend (e.g., in your LDAP
directory, your external SQL database,
etc.) You can either write a script to
do this in advance, or your
authenticate method can do it the
first time a user logs in.