Flask-login with static user always yielding 401- Unauthorized
flask, flask-login, python
Solution
Update:
Since a newer version(0.2.2) of Flask-Login this is no more an issue. Check out the changes in this commit.
If you are using an older version, read on.
The problem here is `static_url_path=""`. For Flask-Login to work you can not have an empty string `static_url_path`.
The following lines in the Flask-Login source(older version) reveal this:
if (current_app.static_url_path is not None and
request.path.startswith(current_app.static_url_path)
):
# load up an anonymous user for static pages
_request_ctx_stack.top.user = self.anonymous_user()
return
Since your `static_url_path` is `""` the if condition evaluates to `True`, because of which every page you visit acts like a static page, and hence Flask-Login always loads an anonymous user, instead of continuing to load the actual user(using the `load_user` callback).
Also do not forget to uncomment `#login_manager.login_view = "login"`
If you still want to use the root folder of the app itself as the static folder, take a look at this solution, using SharedDataMiddleWare:
app.debug = True
if app.config['DEBUG']:
from werkzeug import SharedDataMiddleware
import os
app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
'/': os.path.dirname(__file__)
})
if __name__ == "__main__":
app.run(host="0.0.0.0")
Problem
I am trying to build a super simple web app for my own use. I'll be the only user, so I don't feel the need to involve a database for user management. I'm trying to use flask-login, but even though my call to `login_user` succeeds, I'm still met with a 401-Unauthorized page after the redirect to a page with `@login_required`. Here is the entirety of my app: ``` from flask import Flask, render_template, request, flash, redirect, url_for from flask.ext.login import LoginManager, login_user, logout_user, current_user, login_required, UserMixin app = Flask(__name__, static_url_path="") app.secret_key = "[redacted]" login_manager = LoginManager() login_manager.init_app(app) #login_manager.login_view = "login" class User(UserMixin): def __init__(self, id): self.id = id nathan = User('nathan') @login_manager.user_loader def load_user(userid): if userid == 'nathan': return nathan else: return None @app.route("/logout") @login_required def logout(): logout_user() return redirect(url_for('login')) @app.route('/') @login_required def index(): return render_template('index.html') @app.route("/login", methods=["GET", "POST"]) def login(): if request.method == 'POST': if request.form['username'] == 'nathan'\ and request.form['password'] == '[redacted]': login_user(nathan, remember=True) flash('logged in...', 'success') return redirect(request.args.get("next") or url_for("index")) else: flash('Incorrect username or password. Try again.', 'error') return render_template("login.html"); if __name__ == "__main__": app.run(host="0.0.0.0", debug=True) ``` I've verified that the login actually succeeds (`login_user` returns true) and that `load_user` is returning the `nathan` object. [EDIT] Also, I'm currently using the Flask development server, in case that's relevant. Not sure where I'm going wrong. Thanks in advance!