Python-falcon handling session - python

I am using python flask to build a simple web app, in which user can hit a path say localhost:8000/ and login. if login is successful, another page is displayed, but i want to know how can I redirect to the main page, if the user is already logged in ? for example, if I log in for the first time, I am taken to the main page, and if I open a second tab and again hit the url for login, I am redirected to the main page automatically( much like gmail? ).
class LoginPage(object):
def on_get(self, req, resp, form={}):

For very simple applications HTTP Basic Auth is probably good enough. Flask makes this very easy. The following decorator applied around a function that is only available for certain users does exactly that:
from functools import wraps
from flask import request, Response
def check_auth(username, password):
"""This function is called to check if a username password combination is valid. """
return username == 'admin' and password == 'secret'
def authenticate():
"""Sends a 401 response that enables basic auth"""
return Response(
'Could not verify your access level for that URL.\n'
'You have to login with proper credentials', 401,
{'WWW-Authenticate': 'Basic realm="Login Required"'})
def requires_auth(f):
#wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
return authenticate()
return f(*args, **kwargs)
return decorated
To use this decorator, just wrap a view function:
#app.route('/secret-page')
#requires_auth
def secret_page():
return render_template('secret_page.html')
If you are using basic auth with mod_wsgi you will have to enable auth forwarding, otherwise apache consumes the required headers and does not send it to your application: WSGIPassAuthorization.

Related

How to create a login_required function

I am a new-ish to Flask, and I am trying to create a login_required decorated function for my web app. I would like to make use of session for a user that logs in, which is then cleared once the user logs out.
The session for the user is created like this:
# Creates a session for the users and remembers them.
session['username'] = request.form.get("username")
flash("Logged in!")
Has anyone got any suggestions to create a good login_required decorated function so that users can only access the web-page when logged in?
Thank you.
P.S I saw (and tried) this as a solution (see below) but I received a "working out of request context" error:
def login_required(f):
"""
Decorate routes to require login.
https://flask.palletsprojects.com/en/1.1.x/patterns/viewdecorators/
"""
#wraps(f)
def decorated_function(*args, **kwargs):
if 'username'not in session:
return redirect("/login")
return f(*args, **kwargs)
return decorated_function
There is a nice package for this called Flask-Login
Example:
from flask_login import login_required
#app.route('/my_posts')
#login_required
def my_posts():
...

Basic auth authentication in Bottle

How can i perform basic authentication in bottle framework? in flask i used to:
def check( username, password ):
# This function is called to check if a username/password combination is valid
return username == 'nikos' and password == '******'
def authenticate():
# Sends a 401 response that enables basic auth
return Response( 'Credentials of a registered user required!', 401, {'WWW-Authenticate': 'Basic realm="User!"'} )
and called as:
auth = request.authorization
if not auth or not counters.check( auth.username, auth.password ):
return counters.authenticate()
How can i achieve the same in Bottle framework?
As reported here, Bottle natively contains a decorator that makes Basic Auth pretty straightforward:
from bottle import auth_basic, request, route
def is_authenticated_user(user, password):
# You write this function. It must return
# True if user/password is authenticated, or False to deny access.
#route('/')
#auth_basic(is_authenticated_user)
def home():
return ['hooray, you are authenticated! your info is: {}'.format(request.auth)]
Adapted from ron rothman with a basic auth solution using werkzeug.
from bottle import auth_basic, request, route
from werkzeug.security import generate_password_hash, check_password_hash
users = {'user1': generate_password_hash('pwd!')}
def is_authenticated_user(user, password):
# You write this function. It must return
# True if user/password is authenticated, or False to deny access.
return user in users and check_password_hash(users[user], password)
#route('/')
#auth_basic(is_authenticated_user)
def home():
return ['hooray, you are authenticated! your info is: {}'.format(request.auth)]

userinfo component in Flask URL [duplicate]

I'm trying to create a login system using Flask and HTTP Basic Auth. My question is, is it my responsibility to provide user information from databases, or does basicauth create and access those databases for me? If it doesn't, what can I use to do that?
Werkzeug can decode the Basic Authorization header for you, into the username and password. The rest is up to you to see what you want to do with that information.
The request.authorization attribute returns a Authorization object. For basic authentication headers, only username and password are set.
A project like Flask-Login can help you manage more complex logins with Basic Authorization, and tie that in with a user model you provide. That model can be stored in a database or anything else you so desire.
And you can look at Flask-Security for a more fully integrated security package that uses Flask-Login and other packages to provide Basic Authentication and session based logins.
The Flask-HTTPAuth extension (shameless plug, I'm the author) simplifies the implementation of HTTP Basic Auth. Instead of working with the request.authorization data directly you set up callback functions where you plug the authentication logic.
Regarding your database question, Flask-HTTPAuth makes no assumptions about how your users are stored. You have to provide the logic that retrieves users and validates passwords.
Werkzeug parses the Authorization header into request.authorization, which is an Authorization object.
For security reasons, a browser might only send this header if it first received a 401 error response with a WWW-Authenticate header set. A different client, such as the requests library, will send the header directly.
The simplest demonstration of this is a decorator that checks request.authorization and returns a 401 response if it's not set, or if the credentials were invalid. In practice, you should use an extension such as Flask-Login or Flask-HTTPAuth to manage this.
from functools import wraps
from flask import request
def login_required(f):
#wraps(f)
def wrapped_view(**kwargs):
auth = request.authorization
if not (auth and check_auth(auth.username, auth.password)):
return ('Unauthorized', 401, {
'WWW-Authenticate': 'Basic realm="Login Required"'
})
return f(**kwargs)
return wrapped_view
#app.route('/secret')
#login_required
def secret():
return f'Logged in as {request.authorization.username}.'
import requests
response = requests.get('http://127.0.0.1:5000/secret', auth=('world', 'hello'))
print(response.text)
# Logged in as world.
Here's a Flask Basic authentication example using Python decorator function.
It will return 401, Authentication required if not auth or wrong auth.
Flask API
def check_auth(username, password):
return username == 'username' and password == 'password'
def login_required(f):
""" basic auth for api """
#wraps(f)
def decorated_function(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
return jsonify({'message': 'Authentication required'}), 401
return f(*args, **kwargs)
return decorated_function
#app.route('/', methods=["GET"]
#login_required
def home():
return {"Hello": "world"}
While requesting on server
response = requests.get(url, auth=('username', 'password'))

Flask RESTful API and authenticating for a specific user

I am relatively new to RESTful API, so it is certainly possible I am not designing this correctly.
I want to return a different subsets of a JSON user object from /api/users/[user_id] based on who is authenticating. So if the user "alice" is trying to access /api/users/alice, she would get much more of her info (such as private settings, etc) than user "bob" who would simply get her public profile.
I am currently using flask_restful with httpbasicauth. Right now I have the following:
class UserAPI(flask_restful.Resource):
#g.auth.login_required
def get(self, username):
# here is where I want to get the HTTPBasicAuth username
# to determine how much data to return
user = User.objects(username=username).exclude('password').first()
if user is not None:
return user.to_json()
else:
flask_restful.abort(404, message='User not found: ' + username)
The issue is that I cannot seem to figure out a CLEAN way to get the HTTP basic auth data. I know I could parse the request and decode the base-64 data, but I feel I shouldn't have to do that. Or, even better, find a way to pass the user_id from /api/users/[user_id] into the login_required annotation.
I feel this is would be a very common use case so I can't figure out why I can't find anything in this area. Am I designing this completely wrong?
Thanks very much!
I suggest not using flask.ext.httpauth. I didn't find it very useful. I use a decorator that takes the Authorization header and checks it with the db. You can access the username entered in request.authorization.username and the password is in request.authorization.password.
from flask import request
from flask.ext.restful import abort, Resource
from functools import wraps
def requires_auth(f):
#wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth:
abort(401)
user = User.objects(username=auth.username).first()
auth_ok = False
if user != None:
auth_ok = verify_password(auth.password) == user.password
if not auth_ok:
return abort(401)
return f(*args, **kwargs)
return decorated
class UserAPI(Resource):
#requires_auth
def get(self):
user = User.objects(username=request.authorization.username).\
exclude('password').first()
if user is not None:
return user.to_json()
else:
abort(404, message='User not found: ' + username)

Flask Basic HTTP Auth use login page

I'm building a test app and used the instructions here (http://flask.pocoo.org/snippets/8/) to setup simple authentication. On pages where auth is required I get a popup saying "Authorization Required".
Instead of that, I'd like to redirect to a login page where the user can put their user/pass in a form.
Here's what I have currently (same as the snippet in the link):
from functools import wraps
from flask import request, Response
def check_auth(username, password):
"""This function is called to check if a username /
password combination is valid.
"""
return username == 'admin' and password == 'secret'
def authenticate():
"""Sends a 401 response that enables basic auth"""
return Response(
'Could not verify your access level for that URL.\n'
'You have to login with proper credentials', 401,
{'WWW-Authenticate': 'Basic realm="Login Required"'})
def requires_auth(f):
#wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
return authenticate()
return f(*args, **kwargs)
return decorated
It looks like I could use Flask-Auth, but I really only need the functionality that the above provides.
Thanks,
Ryan
From the documentation, here: http://flask.pocoo.org/docs/0.10/patterns/viewdecorators/. There is a sample decorator that does just this:
from functools import wraps
from flask import g, request, redirect, url_for
def login_required(f):
#wraps(f)
def decorated_function(*args, **kwargs):
if g.user is None:
return redirect(url_for('login', next=request.url))
return f(*args, **kwargs)
return decorated_function
Just return the redirect instead of calling the authenticate() method as you do now.

Categories