Python flask session per user and their own object - python

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.

Related

How to check if user is signed in the frontend of swift App. Backend in python/django-rest-framework

Im trying to make an IOS app with a frontend coded in swift and the back in python using django's rest api.
I have a tab bar controller set up with two tabs, one ultimately connected to a HomeViewController. I have used firebaseAuth, in which I would normally use a firebase function that looked roughly like this
if firebase.Auth.currentUser != nil {
let vc = HomeViewController()
present(vc, animated:True)
}
However, to the best of my knowledge, django's rest api does not have a function of doing so, and so I have been stuck for a few hours now trying to figure this out.
Currently, I am planning on using the cached access token, retrieved on registration/login and sending a get request which returns the users information. (username and email). Then creating a function to decode the data which returns a boolean.
I plan on making a struct
struct AuthenticatedUser: Codable, Hashable {
let username: String
let email: String
}
If it does not confirm to the appropriate struct, the json decoder will fail. (This would be because the get request returned an error as the token was deleted. (In the process of logging out, i would delete the users tokens).
Finally, I will end up with something like this
if decodeData == false {
let vc = HomeViewController()
present(vc, animated:True)
}
Im sure this would work, but even as someone new to programming I can tell that this code seems longwinded, messy and most likely considered as bad code.
I was wondering if anyone had any improvement/new methods (preferably new methods) on combatting this problem.
Any help will be much appreciated!
Well, first your app does not strictly need to know a priori if the current user (which is some data stored persistently within the app) is signed-in in order to access protected user resources successfully (eventually).
The mechanism required in order to make this work, can be entirely embedded transparently into the "client network code", and your views and other parts of your app which perform "protected data access" do not need to know anything about the login scheme, or whether the user is registered or signed-in.
What is signed-in anyway?
What is registered?
What is a user?
Assuming you are using the more common login schemes (OpenID Connect or an custom scheme based in OAuth) which is based on user authentication, user consent and a bearer token, these questions can be answered as follows:
A user which is a struct containing some data about a real user is the identity which has been successfully authenticated. This information is available after user authentication and authorization which usually are the first two steps in the "register user" flow. This can happen on a third party identity provider, but can also be included in your domain server.
Once you have an authenticated user, the app registers this user in our domain database as part of the registration flow. That is, after this step, your user is registered, and that means, it can access the services provided by your domain server.
A user also can "unregister" and its private data and especially, the "user" record on the domain server will be deleted or marked "unregistered".
The processes running on the front end for this, can run on the device or anywhere, for example a web application or a desk top application.
Now, what should be immediately become clear is, that given a certain app on a certain device and just by querying local state, an app never can determine a priori if a user is registered or not, even if the app has a user info.
Now, suppose an app has a "current user" info, and that the user has been registered, but it is not yet "signed-in".
Signing in means, that the app receives a refresh token and an access token. The access token is the key to access protected user resources. When doing this, no user info is required, the access token is implicitly associated to this user.
The refresh token acts as a key to get a new access token, whose expiration time is much longer, possibly quite long, so that it literally never expires (not recommended).
The expiration duration of an access token is usually in the minutes. So, it is quite common that the access token expires all the time.
The access token will be required when accessing a protected resource, so it will be needed for every protected access.
When it is expired, the server sends a very specific unambiguous status code. So, your client code can act accordingly, which means:
push the request on a queue
use the refresh token and ask for a new access token on a certain refresh-token endpoint
Retry the request with the renewed access token
This mechanism is completely transparent to the higher level code and can be implemented quite deeply in the client network code.
Now, in the event that the refresh token is expired too, you again get an unambiguously status code from the refresh-token endpoint.
In this case, it is clear what to do:
Require the user to sign-in again
Step one returns a are refresh token and also access token
Retry the request.
It is clear, that this requires user interaction and will interrupt the current active flow. It should also be obvious, that an app can also not determine a priory if the refresh token has been expired.
Ideally, this "sign-in-again" flow can be pushed on top of any other flow which happens to access a protected resource. Alternatively, just let the refresh-token request fail without opening a sign-in flow, showing a clear error message hinting that the user needs to sign-in again.
The consequences of this is, that you have to try (or just can try!) to access a protected resource in order to find out whether a user is signed in or even registered.
This all has to be implemented in the client network code. Good luck! ;)

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.

How do I persist session data for logins using pyramid_redis_session backend?

I'm using pyramid_redis_session as the backend session_factory. I'm not sure how to go about persisting session data during a login.
As per the pyramid documentation, its simply:
request.session['sid'] = hashedvalue
However, there is also the remember() function for logins. Is remember() to be used for logins and, and the above way to be used for other session data?
The session and the authentication policy are two separate systems. If you want the policy to know that the user is logged in you should use remember to inform it of that fact otherwise you will have the userid in the session but the authentication policy will not know - it typically has its own way of storing who the logged in user is.

What's the difference between authenticate and login?

Documentation: https://docs.djangoproject.com/en/1.7/topics/auth/default/#django.contrib.auth.login
When you’re manually logging a user in, you must call authenticate() before you call login(). authenticate() sets an attribute on the User noting which authentication backend successfully authenticated that user (see the backends documentation for details), and this information is needed later during the login process. An error will be raised if you try to login a user object retrieved from the database directly.
So why exactly is authenticate and login 2 separate functions? From what I understand, authenticate just verifies the login information. login will take the user object and set the cookies. The only reason I can think they are separate is because maybe you can put different user objects in, say the user had 2 accounts merged. Maybe you want to verify the email address first. Is that why they are separate functions and login doesn't wrap authenticate?
This is a matter of the single responsibility principle: a method should do one logical thing. As you noted yourself, these two steps ate logically distinct:
authenticate just verifies the login information.
login will take the user object and set the cookies
To further clarify, authentication is a one-time check,
and doesn't imply a login session.
A login session implies some period of time during which the user is free to perform various restricted activities without repeated authentication checks.
Sometimes you may need to authenticate users (verify they are who they say they are) without logging them in.
If these two functionalities were combined into one,
you wouldn't be able to do that,
even if you just wanted to do a one-time check,
you would have to log them in, creating a session,
which wouldn't make sense.
Since these are clearly distinct purposes,
it makes perfect sense to have two methods.
The separation also makes testing easier. If you write an new authentication backend, you would want to be able to test if the authentication step alone is working or not, without having to worry about how the whole login system works, which is not the responsibility of your backend.
Decomposing methods into their smallest logically independent elements is the sensible thing to do, with many benefits.
In simple terms,
Authenticate refers to verifying the user credentials
Whereas login refers to creation of a user session once the user credentials has been verified(authenticated)
Authentication is the process of identifying users and verifying that they are who they claim to be. A password is one of the most prevalent and visible measures in establishing identity.
The identity is valid if the user name matches the password credential, and the system enables access to the user.
Logging in is the standard process by which an individual receives access to certain resources, computer systems, or networks after being identified and authenticated in the field of computer and information security.
A username is often made up of user credentials, and login is made up of a password.

Categories

Resources