Signout after user disconnects on Flask - python

For those of you who have used flask-login will know the decorator fresh_login_required. I am trying to implement something similar by myself.
It doesn't have to be a decorator. I just want to be able to do some works after the user has been totally disconnected (example: closed the browser).
And is it a good idea to have a global integer variable to count the total active/online users?
Thanks in advance :)

Flask sessions are handled by flask session interface. Flask-Login just check if the current session is fresh.
from flask import session
def login_fresh():
'''
This returns ``True`` if the current login is fresh.
'''
return session.get('_fresh', False)
def login_user():
'''
Your login code here
'''
session['_fresh'] = True
def logout_user():
'''
Your logout code here
'''
if '_fresh' in session:
session.pop('_fresh')
The code snippet above is from Flask-Login source code,that can be accessed here. If you needs the user to login again, just check if his login is fresh.

You should be able to do it with:
#app.before_request
def make_session_permanent():
session.permanent = False
From the docs:
http://flask.pocoo.org/docs/0.11/api/#flask.session.permanent

Related

Trying to use flask principal to restrict access to particular web pages

Hello am new at using flask and I have been trying to figure out how to restrict some web pages unless logged in. I tried flask decorators I tried flask decorators but I couldn't understand it so I tried using flask principal which am able to get it running but still cannot be able to stop the access to that webpage.
Code Description
from flask_principal import Permission, RoleNeed
# create permission with a single Need, in this case a RoleNeed
user_permission = Permission(RoleNeed('User'))
#app.route('/home')
def home_page():
return render_template('home.html')
#app.route('/user')
#user_permission.require()
def do_user_index():
return Response('Only if you are a user')
#app.route('/employee')
def employee_page():
user = User.query.all()
return render_template('employee.html', user=user)
def do_employee_page():
with user_permission.require():
return redirect(url_for('login_page'))
You can use session:
First thing we gonna do is create a session at the moment of login:
#app.route(#route that you gonna use to login data verify)
def login():
#login data verification
flask.session["user data"] = #Data you want to use to identify the user
#the next step that you wanna do
Now we gonna verify the session data in the pages, if the user are log in they gonna have their data in flask.session and if not, they not going to have the data in session.
#app.route('/user')
def do_user_index():
if "user data" not in flask.session:
#Redirect to the login page
return Response('Only if you are a user')
You can consult the documentation to learn more about the how to use session.
https://flask.palletsprojects.com/en/2.0.x/quickstart/#sessions

Flask session log out and redirect to login page

I am using Flask,Python for my web application . The user will login and if the session time is more than 5 minutes then the app should come out and it should land on the login page.
I tried some of the methods and I can see the session time out is happening but redirect to login page is not happening.
#app.before_request
def before_request():
"Session time out method"
flask.session.permanent = True
app.permanent_session_lifetime = datetime.timedelta(minutes=2)
flask.session.modified = True
flask.g.user = flask_login.current_user
#return redirect(url_for('login'))
I have used before_request for seesion time out.
I have referrred this link Flask logout if sessions expires if no activity and redirect for login page
but I dont see any changes from what I have tried before and this code. I can see lot of stackoverflow questions over there for this topic and I couldnt find the solution.
I have tried this link als
Expire session in flask in ajax context
But I am not sure what should I pass as a session and what qualifier I should return here?
#mod.before_request
def make_session_permanent():
if session_is_invalid(session):
return redirect(url_for('logout'))
def session_is_invalid(ses):
# return your qualifier
if the previous method is correct can some one tell me what is the session and what qualifier I should return here?
What I need is after session log out the page should automatically land on the login screen
What is happening is session log out is happening but it's not redirecting to login page
could some one help me in this?
When I read the documents of the Flask-Login package, i saw a few things. When creating your Flask application, you also need to create a login manager.
login_manager = LoginManager()
A login_view variable in LoginManager class caught my attention. The details include the following explanation:
The name of the view to redirect to when the user needs to log in. (This can be an absolute URL as well, if your authentication machinery is external to your application.)
Actually, after you create a LoginManager object,
login_manager.login_view = 'your login view'
You should specify your login page. Finally,
Once the actual application object has been created, you can configure it for login with:
login_manager.init_app(app)
After doing these, any unauthorized calls to every method you use #login_required annotation will be sent to the page you have pointed out with login_view.
I also developed a simple application. You can review this application from here. I tested it and working without any problems.
I hope it helps you.

Flask-login currentuser becomes anonymous after server restart

I successfully completed my web app with Flask ad deployed it on my server. I use current_user in some of my methods and I need that information for some purposes. Lately I noticed a problem. There was already logged in pages and at that point I restarted flask server. Logged in pages were untouched during that. And current_user became anonymous in all open and previously logged in pages. To prevent that, I tried such:
#app.before_request
def make_session_permanent():
session.permanent = True
But still the same problem What should I have done? At least I would like to force all client pages to go to login page after server restart.
with app.secret_key = os.urandom(12)I was using a changing secret key. I did it so that app.secret_key = 'sansal54' and it was solved.

Redirect to login page after session expiry - Python Flask App

I have a python flask app with login module implemented using extension python flask. In my login method, I have set below
def login():
.......
.......
session.permanent = True
app.permanent_session_lifetime = datetime.timedelta(minutes=3)
......
......
This code sets my session cookie to 3 minutes as expected.
What's happening right now is, after 3 minutes, the page is still active and sending GET requests and POST request even the session is expired. What I want is after session is expired the page to default to login page.
Does flask-login provides this functionality out of box? Any suggestion would be helpful
Thanks
Using flask-login, do this, it will automatically redirects to login page.
#app.before_request
def before_request():
flask.session.permanent = True
app.permanent_session_lifetime = datetime.timedelta(seconds=30)
flask.session.modified = True

Testing Flask login and authentication?

I'm developing a Flask application and using Flask-security for user authentication (which in turn uses Flask-login underneath).
I have a route which requires authentication, /user. I'm trying to write a unit test which tests that, for an authenticated user, this returns the appropriate response.
In my unittest I'm creating a user and logging as that user like so:
from unittest import TestCase
from app import app, db
from models import User
from flask_security.utils import login_user
class UserTest(TestCase):
def setUp(self):
self.app = app
self.client = self.app.test_client()
self._ctx = self.app.test_request_context()
self._ctx.push()
db.create_all()
def tearDown(self):
if self._ctx is not None:
self._ctx.pop()
db.session.remove()
db.drop_all()
def test_user_authentication():
# (the test case is within a test request context)
user = User(active=True)
db.session.add(user)
db.session.commit()
login_user(user)
# current_user here is the user
print(current_user)
# current_user within this request is an anonymous user
r = test_client.get('/user')
Within the test current_user returns the correct user. However, the requested view always returns an AnonymousUser as the current_user.
The /user route is defined as:
class CurrentUser(Resource):
def get(self):
return current_user # returns an AnonymousUser
I'm fairly certain I'm just not fully understanding how testing Flask request contexts work. I've read this Flask Request Context documentation a bunch but am still not understanding how to approach this particular unit test.
The problem is different request contexts.
In your normal Flask application, each request creates a new context which will be reused through the whole chain until creating the final response and sending it back to the browser.
When you create and run Flask tests and execute a request (e.g. self.client.post(...)) the context is discarded after receiving the response. Therefore, the current_user is always an AnonymousUser.
To fix this, we have to tell Flask to reuse the same context for the whole test. You can do that by simply wrapping your code with:
with self.client:
You can read more about this topic in the following wonderful article:
https://realpython.com/blog/python/python-web-applications-with-flask-part-iii/
Example
Before:
def test_that_something_works():
response = self.client.post('login', { username: 'James', password: '007' })
# this will fail, because current_user is an AnonymousUser
assertEquals(current_user.username, 'James')
After:
def test_that_something_works():
with self.client:
response = self.client.post('login', { username: 'James', password: '007' })
# success
assertEquals(current_user.username, 'James')
The problem is that the test_client.get() call causes a new request context to be pushed, so the one you pushed in your the setUp() method of your test case is not the one that the /user handler sees.
I think the approach shown in the Logging In and Out and Test Adding Messages sections of the documentation is the best approach for testing logins. The idea is to send the login request through the application, like a regular client would. This will take care of registering the logged in user in the user session of the test client.
I didn't much like the other solution shown, mainly because you have to keep your password in a unit test file (and I'm using Flask-LDAP-Login, so it's nonobvious to add a dummy user, etc.), so I hacked around it:
In the place where I set up my test app, I added:
#app.route('/auto_login')
def auto_login():
user = ( models.User
.query
.filter_by(username="Test User")
.first() )
login_user(user, remember=True)
return "ok"
However, I am making quite a lot of changes to the test instance of the flask app, like using a different DB, where I construct it, so adding a route doesn't make the code noticeably messier. Obv this route doesn't exist in the real app.
Then I do:
def login(self):
response = self.app.test_client.get("/auto_login")
Anything done after that with test_client should be logged in.
From the docs: https://flask-login.readthedocs.io/en/latest/
It can be convenient to globally turn off authentication when unit testing. To enable this, if the application configuration variable LOGIN_DISABLED is set to True, this decorator will be ignored.

Categories

Resources