I have a sample Flask app which mostly works. The base URL (/
) doesn't require authentication; however, I have a resource at /auth/secured
, which requires authentication.
The app works very well as long as a user is logged in; however, it throws a werkzeug.routing.BuildError (BuildError: Could not build url for endpoint 'login' with values ['next']. Did you mean 'auth.login' instead?)
when someone tries to access /auth/secured
as an unauthenticated user, because I have it coded like this:
@auth.route('/secured')
@ldap.login_required
def secured():
return 'Login Success! {0}'.format(session)
I'm using Flask Blueprints for my URL routing... I assumed this should work...
def create_app(config_name):
from .main import main as main_blueprint
from .auth import auth as auth_blueprint
# Configure the flask instance...
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
# Initialize the application...
bootstrap.init_app(app)
db.init_app(app)
ldap.init_app(app)
# Blueprint registration
app.register_blueprint(main_blueprint)
app.register_blueprint(auth_blueprint, url_prefix='/auth')
return app
The app directory is built as follows:
testapp/
|
+ config.py
+ manage.py
+ app/
|
+ __init__.py
+ auth/
|
+ __init__.py
+ views.py
+ main/
|
+ __init__.py
+ views.py
As best I can tell, something is messed up in my blueprint registration; however, I'm at a loss for where the error is.
How do I make an unauthenticated user redirect correctly to the /auth/login
URL when they surf to /auth/secured
as an unauthenticated user?
Looks like there are a couple of problems.
The first is a missing config parameter, LDAP_LOGIN_VIEW
. The default is login
but since you don't have a view named 'login', you probably want to set this to be auth.login
in your config file:
LDAP_LOGIN_VIEW = 'auth.login'
The next issue is that your auth.login
doesn't handle a next parameter. The next parameter tells the login function where to redirect after a successful login. This might cause a problem since flask-simpleldap is passing a next parameter here.
return redirect(url_for(current_app.config['LDAP_LOGIN_VIEW'],
next=request.path))
You can access the next parameter through the request object.
Example:
from flask import request
@app.route('/login', methods=['POST', 'GET'])
def login():
error = None
if request.method == 'POST':
if valid_login(request.form['username'],
request.form['password']):
return log_the_user_in(request.form['username'])
else:
error = 'Invalid username/password'
# the code below is executed if the request method
# was GET or the credentials were invalid
return render_template('login.html', error=error)