4

I am working with the Flask-Security extension and can't for the life of me figure out where in the extension I can pass in an unauthorized handler at the time the extension is initialized. This is important to me because I don't want to redirect a user to another endpoint when they don't have a required permission. I want them to see it in the url where they are, so they retain the context of the url they don't have permission to access. My work around is to monkey patch the method onto the extension before the first request comes in:

@app.before_first_request
def monkey_patch():
    """Monkey patching the flasksecurity callback"""
    current_app.extensions['security']._unauthorized_callback=lambda: abort(401)

I then use my app.errorhandler to take care of the error and return an appropriate response code.

@app.errorhandler(401)
def unauthorized(e):
    return 'You not authorized to visit this page', 401

Does anyone know of a better way to do this?

user2521226
  • 41
  • 1
  • 4

1 Answers1

3

I have the same issue - I'd like my application returned JSON object instead of redirection to login page once user tried to access a restricted area. Looks like Flask-Security does not provide such functionality out of box. Fortunately it reuses Flask-Login and exposing it as member of flask application.

That is how it works. Now once user trying to access API endpoint secured with login_required decorator it returns JSON object.

@app.login_manager.unauthorized_handler
def unauth_handler():
    return jsonify(success=False,
                   data={'login_required': True},
                   message='Authorize please to access this page'), 401

Hope this help!

UPDATE: I updated function a bit to make it more versatile. If request passed is AJAX then it responds with JSON object, otherwise with rendered page.

@app.login_manager.unauthorized_handler
def unauth_handler():
    if request.is_xhr:
        return jsonify(success=False,
                       data={'login_required': True},
                       message='Authorize please to access this page.'), 401
    else:
        return render_template('errors/401.html'), 401
Community
  • 1
  • 1
Alex G.P.
  • 9,609
  • 6
  • 46
  • 81
  • What exactly is `app` in this context? I am asking because the Flask app does not have a `login_manager`; at least my PyCharm claims it. – tafaust Aug 17 '18 at 09:34
  • @Thomas of course it hasn't. `app` is Flask all. `login_manager` is injected object provided by either `Flask-Login` or (I used it) `Flask-Security`. You have to install and setup it by yourself. – Alex G.P. Aug 17 '18 at 10:54