简体   繁体   中英

Simplest authentication with flask-restless

I am using Flask-Restless to make a super simple REST API. I would like to add authentication, but just for put/post/delete calls, while I want to leave get calls public.

So far, I put in my views.py file this:

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

I had a look on different solutions for authentication, but they all look too "big". I'll have just one user that should be able to make PUT/POST/DELETE calls, and then "public" users will just use GET.

I think that a simple way should be something like this:

  • Public users making a get call: return the api response, as it is now
  • Public users making a put/post/delete call: return the "not authorized" response
  • Registered user making get/put/post/delete calls: check if it is registered and reply the appropriate response.

The "check" shouldn't be something like storing a secret-key in my config.py file and then comparing it to an attribute of the header of the api call? I think that creating an entire table for users, as I saw in some tutorials, and then having usernames+password that generates API tokens is too "big" and not necessary here.. Since I will be the only user that can be authenticated, I know what the key is and I can just put some 'secret-key' : mysecretkey in the header. Am I missing something?

Thanks!

This can be done using preprocessors argument of create_api . For example:

# replace the next line with your favorite way or reading config files
access_password = 'mysecretkey'

def check_credentials(**kwargs):
    if flask.request.headers.get('X-Secret-Key','') != access_password:
        raise flask_restless.ProcessingException(code=401)  # Unauthorized

# create API
manager = flask_restless.APIManager(app, flask_sqlalchemy_db=db)
manager.create_api(models.mymodel, methods=['GET', 'POST', 'DELETE'],
                   collection_name='myobjects',
                   preprocessors={
                        'POST': [check_credentials],
                        'DELETE_SINGLE': [check_credentials],
                   })

Tested with Python 3.4, Flask 0.11.1, Flask-Restless 0.17.0. Older versions for Flask-Restless may require DELETE instead of DELETE_SINGLE , and a different package name.

An example how to access the password-protected part of the API using cURL:

curl -X POST -d '{"data":"my JSON data, etc."}' \
     -H "Content-Type: application/json" \
     -H "X-Secret-Key: mysecretkey" \
     http://localhost:5000/api/myobjects

This is a simple scheme, but if there is any chance you app may grow bigger in the future, I would recommend going with Flask-JWT . It doesn't have to be big and complicated with a database back-end. Here is your starting case (one used with a hardcoded password) in a minimalist implementation:

# Anonymous object is sufficient here, a full-blown solution would define a class User
admin_user = type('', (object,), {"id": 1, "username": "admin", "password": "mysecret"})()

def authenticate(username, password):
    if username == admin_user.username and password == admin_user.password:
        return admin_user

def identity(payload):
    id = payload['identity']
    if id == admin_user.id:
        return admin_user


jwt = JWT(app, authenticate, identity)


@jwt_required()        
def check_credentials(**kwargs):
    pass

# create API as in the first example

Tested with Python 3.4, Flask 0.11.1, Flask-Restless 0.17.0, Flask-JWT 0.3.2.

you can try flask-jwt , it's easy to integrate. It also has a simple example there. I'm also find a way to implement something like your 3rd bullet point, please share if you have any solution.

No need to reinvent authentication when HTTP Basic Auth exists:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM