I was going through some examples on how to implement oauth2 with a Google App Engine application and after deploying, I noticed that my #decorator.oauth_aware redirects the user to log-in page by default...
I found a similar question here but there is no actual solution on how to go about with it :
class RootHandler(handlers.BaseHandler):
#decorator.oauth_aware
def get(self):
variables = {'has_credentials' : decorator.has_credentials()}
if decorator.has_credentials():
#do something
variables.update( {
'url': decorator.authorize_url()
})
return self.render('index.html', variables)
What I want is, if the user is not logged-in/doesn't have credentials, display the index page with a sign in button (that has the authorisation url) and only afterwards redirect to root again and display further info.
Related
After days of reading through the source code of Flask and Flask-Login and trying to figure out why my user sessions aren't being visibly accessible outside the route where the session is set, I am convinced that the response sent by Flask API is causing the issue.
I have tried to reverse engineer some of the tutorials that are present on the internet to use Flask-Login, however, most of them rely on using Jinja templates. This posed a challenge as I had to figure out a way to make it work with a React frontend. I initially used the examples with jinja templates as an example as I was building out the React frontend and I was immediately faced with some issues.
I have the following routes: /login and /logout. I also utilized current_user from Flask-Login to access session details. So for example:
If the /login route is accessed and current_user is authenticated, then nothing happens.
If the /login route is accessed and current_user is not authenticated, then the authentication logic is run, session is now updated to include the authenticated user and user is logged in
If the /logout route is accessed and current_user is not authenticated, nothing happens
If the /logout route is accessed and current_user is authenticated, then the session is cleared and used is logged out
I was able to get the first two from above to work, however, when the user is logged in, the session appears to not been saved and I am not able to log out.
Below are two different code snippets:
Jinja Templates
#auth.route('/login')
def login():
return render_template('login.html')
#auth.route('/login', methods=['POST'])
def login_post():
email = request.form.get('email')
password_hash = request.form.get('password')
user = RegisteredUser.query.filter_by(email=email).first()
if user is not None and user.check_password(password_hash):
login_user(user)
return redirect(url_for('main.profile'))
return redirect(url_for('auth.login'))
JSON Object Response
#auth.route('/login', methods=['GET', 'POST'])
def login_post():
if current_user.is_authenticated:
return jsonify({ 'login' : True })
data = request.get_json()
user = RegisteredUser.query.filter_by(email=data['user']).first()
if user is not None and user.check_password(data['password']):
login_user(user)
return jsonify({ 'login' : True })
return jsonify({ 'login' : False })
The code example using Jinja templating works and the session is saved after all the code is finished executing when the /login route is accessed. However, this is not the case for the code returning JSON data.
This leads me to believe that in order to properly use Flask-Login, developers would need to make custom Flask Response objects (i.e. look like - redirect(url_for(...)) or render_template(...)) and reconstruct how the response would look like if Jinja templating was used.
I was wondering if anyone else had experienced this or is there a different path I could take that would be better.
Thanks.
Edit:
I am now open to different possible solutions. If I don't use flask-login, what are other options for user session management for React and Flask?
I have looked into flask-security, flask-user, flask-session, but they don't seem to be maintained as much as flask-login.
I am ideally looking at cookie-based solutions.
For my solution, I scrapped using Flask-Login and went another path.
Since what I did may unintentionally reveal confidential stuff, I will provide a high-level overview. Feel free to ask questions as I have saved all the resources that led me to figuring out what to do.
I decided to use Google's Firebase API (For the frontend) and Admin SDK (For the backend).
Admin SDK uses session cookies, so if you have two separate servers here are some topics that you might want to look into
Cross-origin resource sharing
Cross-domain cookies
Subdomains (This relates to the point above)
Because I am using cookies, something that I had to be mindful of is CSRF attacks. For this, I am using Flask-WTF extension because it has an implementation to prevent it.
However, in the event of any errors such as:
CSRF token is missing
CSRF session token is missing
CSRF session token expired
etc
Flask-WTF by default doesn't return anything back to the client (at least if running two separate servers). When an error occurs, it just displays a 4XX page. As a result, I forked the repository source code such that I can get some kind of 4XX response to the client.
I am not a security expert by any means, but I have learnt quite a bit of small things along the way. Be sure that a secure connection is always in place. Also, make sure when you are setting up subdomains, be very careful as you don't want to fall victim to subdomain takeovers.
Cheers!
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
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.
So I'm working with AppEngine (Python) and what I want to do is to provide OpenID Login setting a Default provider so the user can Log-In without problems using that provider. The thing is, I want to prompt the user a Password right after they login in order to show static content (HTML Pages); If the user doesn't enter the correct password then I want to redirect them to another page. The protection has to be server side please :) Any Ideas??
P.S. I'm seeking for a solution similar to ".htaccess/htpasswd" but for app engine.
AFAIK, GAE does not support such setup (static password after OpenID login).
The only way I see to make this work would be to serve static content via your handler:
Client makes a request for static content
Your handler is registered to handle this URL
Handler checks is user is authenticated. If not, requests a password.
When authenticated, handler reads static file and sends it back to user.
Try this out, you can mimic the .htaccess style password with Google App Engine:
def basicAuth(func):
def callf(webappRequest, *args, **kwargs):
# Parse the header to extract a user/password combo.
# We're expecting something like "Basic XZxgZRTpbjpvcGVuIHYlc4FkZQ=="
auth_header = webappRequest.request.headers.get('Authorization')
if auth_header == None:
webappRequest.response.set_status(401, message="Authorization Required")
webappRequest.response.headers['WWW-Authenticate'] = 'Basic realm="Kalydo School"'
else:
# Isolate the encoded user/passwd and decode it
auth_parts = auth_header.split(' ')
user_pass_parts = base64.b64decode(auth_parts[1]).split(':')
user_arg = user_pass_parts[0]
pass_arg = user_pass_parts[1]
if user_arg != "admin" or pass_arg != "foobar":
webappRequest.response.set_status(401, message="Authorization Required")
webappRequest.response.headers['WWW-Authenticate'] = 'Basic realm="Secure Area"'
# Rendering a 401 Error page is a good way to go...
self.response.out.write(template.render('templates/error/401.html', {}))
else:
return func(webappRequest, *args, **kwargs)
return callf
class AuthTest(webapp.RequestHandler):
#basicAuth
def get(self):
....
How-To: Dynamic WWW-Authentication (.htaccess style) on Google App Engine
from bottle import route, run, debug, error, request, template
#route('/home')
#route('/home/')
def login():
return template('templates/login')
#route('/home', method='POST')
#route('/home/', method='POST')
def welocme():
data = request.POST
if data:
password = data.get('password')
check_pass = 'password'
if password == check_pass:
return template('templates/welcome')
else:
return template('templates/login')
else:
return template('templates/login')
My requirement is:
I will get a login and welcome page on same url. Login page has only one password field.
My problem:
If I get login and go to welcome page again on refreshing, it send me to login page. But ideally it should be on the welcome page only.
#error(404)
def error404(error):
return 'http://google.com'
My second problem: I want to redirect on a particular url on 404.
If the user goes to the "/home" page, don't you want to check to see if they're logged in before showing them the login screen? It appears like you assume they're not already logged in if the HTTP method is not POST.
I don't know much about your framework, but I assume if the login is successful you should set a cookie, and then you should check the cookie for HTTP GETs to see if the user is authenticated.
Your second question is answered here.
You might also want to take a look at Beaker's cookie sessions and use that to keep your application's state between requests.
If I understand the question correctly, the only way to get to render the welcome template is via POST.
You could change this so that GET requests check whether someone is logged in. If that fails, then redirect them to the login page.