Motassem Kassab
Motassem Kassab

Reputation: 1815

Python / Flask - Using flask_restless with flask_httpauth

my objective in this question is to secure my API.

in my application, I'm using Flask and flask_restless's APIManager to provide CRUD API to my Person object.

code sample:

manager = APIManager(app, flask_sqlalchemy_db=db)
manager.create_api(Person, methods=['GET', 'POST', 'PATCH', 'DELETE'])

and also using flask_httpauth to protect my other routes like this:

@app.route('/auth/get-token')
@auth.login_required
def get_auth_token():
    token = g.user.generate_auth_token()
    return jsonify({'token': token.decode('ascii'), 'fullname': g.user.fullname})

I could not figure out how to use @auth.login_required with the apimanager to not make it respond to anonymous requests, I read in the documentation something about preprocessors but also couldn't find a way to use it with @auth.login_required decorator.

any help will be appreciated.

Upvotes: 1

Views: 309

Answers (2)

Miguel Grinberg
Miguel Grinberg

Reputation: 67499

Unfortunately, it looks like Flask-Restless currently does not officially support attaching view decorators to the routes it manages. There is an open issue to add this feature, and there is also another issue specifically requesting support for Flask-HTTPAuth.

There is yet a third issue, in which a user shows the technique to manually inject the decorators after Flask-Restless created its endpoints. The snippet from that user's example that adds a get_cache decorator is below:

manager = flask.ext.restless.APIManager(app, flask_sqlalchemy_db=db)
manager.create_api(Person, methods=['GET', 'POST', 'DELETE'])
manager.create_api(Person2, methods=['GET', 'POST', 'DELETE'])

# hackish view decoration:
for model in [Person, Person2]:
    model_route = '{0}api0.{0}api'.format(model.__name__.lower())
    app.view_functions[model_route] = get_cache(app.view_functions[model_route])

In your case, you would replace get_cache with auth.login_required.

Update: As discussed below in the comments, the argument in '{0}api0.{0}api' is the table name, so the above code will only work if table names are left for Flask-SQLAlchemy to generate. If the model has a custom table name, then use that instead of model.__name__.lower().

Upvotes: 2

stamaimer
stamaimer

Reputation: 6475

I recommend you to use Flask-Security. There is a tutorial about how to use it to security your API interface.

Upvotes: 1

Related Questions