Eliminating certain Django Session Calls - python

I was wondering if I could eliminate django session calls for specific views. For example, if I have a password reset form I don't want a call to the DB to check for a session or not. Thanks!

Sessions are lazily loaded: if you don't use the session during a request, Django won't load it.
This includes request.user: if you access it, it accesses the session to find the user. (It loads lazily, too--if you don't access request.user, it won't access the session, either.)
So, figure out what's accessing the session and eliminate it--and if you can't, at least you'll know why the session is being pulled in.

Related

Do `Users` need to exist in Django for SSO?

Basically, I am implementing the following functionality where the Front end will send signed JWTs to the backend. If the backend is able to decode and hence validate the Token (i.e. the signature, claims, audience, etc), then it will give access to the protected API resources:
Now the users already exist in Azure AD (so I don't want to have to create/manage users in the Django DB as well). So essentially all I want to do is protect the Django Restful API endpoints with validated Access Tokens. I was looking at Custom Authentication (by extending rest_framework.authentication.BaseAuthentication) but it seems that the authenticate method expects a User to be matched (Hence Users to exist) and returned for a successful authentication (I would like to just pass if JWT validation is a success or raise Exception is there is an error).
Django docs:
Either way, authenticate() should check the credentials it gets and return a user object that matches those credentials if the credentials are valid. If they’re not valid, it should return None.
I have achieved my desired flow (i.e. having no Django Users) using method_decorator but this does not seem like a correct pattern for authentication:
class ComponentViewSet(viewsets.ModelViewSet):
queryset = Component.objects.all()
serializer_class = ComponentSerializer
#method_decorator(validate_jwt)
def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)
Django docs also state that:
The Django admin is tightly coupled to the Django User object. 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.
I have also done a separate implementation of the Custom Authentication by creating Users on the fly in the authenticate method just as the documentation recommended.
So my question is, is having Users exist in Django a strongly recommended design (or must according to the docs) even when you have a centrally managed Authentication system like LDAP/AD etc? Or is it also common not to use the Users model and use some other kind of implementation (for example the method decorator I used) when you don't intend to hold any kind of User information in the backend because I see it as redundant? Are there any advantages of duplicating a users database in the Django backend if it is strongly recommended. And do these users also require passwords if they extend django.contrib.auth.models.User?
Rather than needing to use a decorator on every method, just make your own authentication backend. When a view calls authenticate(), Django calls all backends specified in AUTHENTICATION_BACKENDS until one doesn't return None.
In regards to storing users, Django assumes by default that you want to store session data in the backend, to not require login. If you're fine with reauthenticating on every request, then you can feasibly just return a new instance of BaseUser object, without saving to the database, although other Django functionality might break in unexpected ways.
You might want to explore creating your own user model based on AbstractUser or even AbstractBaseUser. If you're not getting a new token on every request, it makes sense to store the token in the user model, along with a when_authenticated, time_to_expiry, etc.
A new user OR a returning user who's when_authenticated + time_to_expiry < now() access token will be validated with the auth server. On success, update the necessary time fields, along with current_access_token. Subsequent requests within your refresh window merely have to do a fast equality check, as opposed to another request to the server.
This will save your auth server from lots of requests, speed up your API (no auth server validation on every call), and still let you use some of the awesome functionality Django lets you have with users.

how to make ensure one active session per one user using python flask?

how to make ensure one active session per one user using python flask?
Description: if one user logged in two different machines with same credentials
I want mechanism to force logout earlier active sessions of that user with flask and python. Please help me out in this.
I am currently using flask-login, load_user() and login_manager libraries for login mechanism.
One way for ensuring this would be by generating a session id from server. You would need to generate a unique session id every time a user logs in and store it in some database against that user. Apart from this you would need to authenticate user every time an endpoint call, which requires user to be logged in, is made. And of course discard the session id on logout.
This way whenever a user logs in the old session id is discarded and the previous session no more remains valid.

Access request object from within django admin's authenticate()

Is this anyhow possible to access the request object from within the django admin's authenticate() in custom auth backend?
The reason for this is I want to keep and re-use the user's password (or a Kerberos ticket - not sure yet) to authorize an operation in another system, which uses the same LDAP backend. For this purpose I wanted to use request.session - but it doesn't seem to be accessible, at least not the easy way.
If there's any other possibility to pass a value from the auth to the model, I'd be happy to get a suggestion as well.
Thanks.
I believe it's a bad idea to store raw password in session for security reasons, but some ideas (just ideas, never tried it):
Access session directly https://docs.djangoproject.com/en/1.10/topics/http/sessions/#using-sessions-out-of-views
Make sure your session won't be flushed by django.contrib.auth.login. See details in implementation.
user_logged_in signal has access to request and user object.
user_logged_in.send(sender=user.__class__, request=request, user=user)
Looks like you can add attribute to user object inside authentication backend method and later attach it to session.

Allowing Users logged in with multiple accounts at once to the same Django site

I'm creating a widget that gets installed on various different sites and I need distinct users for each site. Problem is, the same person browsing might have 2 different sites open at once that use my widget. This means that I need users to be logged in with multiple accounts simultaneously to the same Django site.
From my understanding, Django usually assumes that only 1 user is logged in per session.
What's the simplest and most effective way to go about this?
I ended up storing the per-site data in the user's session, i.e. session['site_id_1'] = user_obj_1, session['site_id_2'] = user_obj_2, etc...
Instead of logging in, I just store the user data in the appropriate key. Instead of logging out, I delete the key for the site.
I think you have to rewrite the session middleware. In the default implementation the session is stored in the database, the session_key is saved in a cookie and the cookie_name is defined in settings.py.
So if you write your own session middleware, you can define different cookie names for every site and retrieve the session from the database accordingly. django.contrib.sessions.middleware.SessionMiddleware is a good template.

Python flask session per user and their own object

I'm hopeful someone can point me at the proper way to implement this situation.
I'm building a flask app for multiple concurrent users. The app essentially wraps a back-end RESTful service that requires authentication and will allow commands to be sent. The users do not need to login the flask app itself, but they do provide credentials that I use to authenticate an object to the Restful service. As such, each user needs their own unique object for their particular session. For ease of use/laziness I'm also storing some trivial information in a few session['x'] variables.
The session information is not unique to each user and it appears the last user to "login" clobbers the previous users' authentication object.
What is the proper way to build this? I could move the session variables into the object, but that still leaves the problem that all users require their own back-end object. Do I need to implement a true flask-login?
I have used the flask-login extension in the past to implement login and session management systems.
One issue with storing user information in a python object like session is that you will never be able to scale your application beyond one process. In almost all cases you will want to have more than one process handling requests. Each process will be running with its own python interpreter and will not share the session object. You really want a database that is shared by all processes to store session information, redis works great for this purpose.
For flask-login you need to implement a user class and two functions (best implemented as methods of the user class):
A login function that will authenticate the provided username and password against your service and then generate a large random number (16-32 bytes) using a cryptographically secure pseudo-random number generator (i.e. os.urandom()) to use as a session id. Use the generated session id as the key to the user's session information in a sessions table or database and as the id of your User class. The login function should return your User object. I normally implement it as a classmethod of the User class.
A load_user callback that will take a session id generated in the above function and return the class representing your user populated with information from the database that is storing your session information
Flask-login will handle securely storing (as a HMAC) your session id on the user's computer as a cookie and at the beginning of requests it will call your load_user callback to retrieve the user's information. Logged in users' information will be available by importing the current_user proxy from flask_login (from flask_login import current_user). This object is also available in jinja templates.

Categories

Resources