简体   繁体   中英

Passing Flask-Login authentication from web app to API

I'm in the process of writing a tool in Flask that has both a direct API interface and a Web interface that uses the API under the hood. So for example to create a new group with the tool, you could do it in either of these two ways:

API method

  • POST a JSON object to http://example.net/api/addgroup with all the parameters to create the group. (Authentication is passed via HTTP Basic Authorization. Flask-Login authenticates the user from a local users DB)
  • Assuming the user is authorized, the API creates the group, sets the “owner” to the logged-in user, and returns JSON with success/failure information.

Web method Go to http://example.net/addgroup

  • Log in (again Flask-Login authenticates the user from a local users DB)

  • Fill out the form

  • Click Submit

  • Web app calls the API app under the hood, parses the JSON it gets back, and shows the user a success/fail message

Now the tricky part is in bold there, where the Web interface is calling the API interface on the backend (using the Python “requests” module). By default, no authentication is being passed to the API. But that won't work – the API needs authentication info for authorization and in order to assign the “owner” when it creates the group.

I can think of a couple of ways for the web app to pass authentication to the API:

  1. Store the user's password in the Flask session so that the “requests” module can generate a Basic Authorization header to impersonate the user when it calls the API. (But I suspect this is a Bad Idea.)

  2. Create a privileged account (with its own password) for the web app. Have the web app use that account to call the “requests” module and pass in an “owner” value which is the userid of the actual user. (The API would be configured to allow “owner” to be passed through only by that privileged account. All other usages of the API would take the owner from the logged in current_user).

Is it appropriate (and safe!) to use either of these methods? Or is there another way entirely for the web app to pass authentication to the API?

UPDATE 2016-07-11

As mentioned in the comments below, I'm not opposed to directly calling the API classes within the app, thereby avoiding the need to make an HTTP request at all. But I don't know how to do that with Flask-Restful , which implements GET and POST like this:

class MakeList(Resource):

    def get(self, group_id=None):
        # Do GET stuff here

    def post(self, group_id):
        # Do POST stuff here

api.add_resource(MakeList, '/api/makelist', '/api/makelist/<int:group_id>', \
                 endpoint='api-makelist')

How would I call the "get" or "post" method from elsewhere in the Flask app?

What I would do, and I believe what @Sugam was suggesting, is to create a Python library containing the business logic. Extract the BL code from Web API into this library, then call the library from Web API. This way the api project is just a facade providing RESTful access to the methods in the library.

This will allow you to expose the business logic through other UI forms, like CLI (console), library API (if you want to use it in another application), mobile apps, web, etc. This, naturally, allows you to call the same Python library from your Web site, completely avoiding making any sort of network calls through the Web API project.

Moreover, you will be able to write tests that clearly demonstrate the usage, and confirm that it does what it is supposed to do, while avoiding the unnecessary detail, like protocols, formats, and so on.

Hope this explanation is clear enough.

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