osmlab / to-fix-backend

The to-fix server
BSD 3-Clause "New" or "Revised" License
15 stars 13 forks source link

[Postgis] Handling user authentication #115

Closed batpad closed 7 years ago

batpad commented 7 years ago

Refs https://github.com/osmlab/to-fix-backend/pull/113

I see a few options here:

  1. The current backend receives the callback from OSM at a backend URL - it uses the access_key and access_secret passed from OSM to query the user details from OSM. After verifying the user details, it checks if the user exists in a users table or else it creates a new user. All users have a JWT token generated, and the back-end sends this token to the frontend. The frontend uses the JWT token for all further authenticated requests. We are able to store permission levels, etc. in the users table. It would also be trivial to then create users that do not have OSM accounts, by creating an entry in users and generating a JWT token.

  2. The other option is to do purely client side authentication, and this seems insecure to me -- i.e. OSM redirects to a frontend URL after the user logs in and passes the access_key and access_token -- the frontend looks up the user details using these keys, and then for authenticated requests, sends across these user details to the back-end. This makes it easy / possible for a malicious user to fake user details being sent from the frontend, since the OSM auth is not actually verified on the back-end.

  3. From what I understand looking at the boilerplate code you have sketched out @mcwhittemore, seems like you envision the client sending the access_token and access_secret with every request that needs to be authenticated. The backend would then, for every request, query OSM to fetch user details and authenticate the user. This saves us having to maintain a users table or tokens of our own, but I worry greatly about calling out to the OSM API for every user request that requires authentication - the OSM API can definitely be slow sometimes, and I'd worry about adding that extra overhead for every request.

Happy to go with any of these routes, but just wanted to make sure we're on the same page here -- I would prefer to just implement 1>, which I feel puts user handling more under our control, allows for more flexible permissions and non-OSM authentication options. Of course, the overhead here is that we would need to manage a users table, so am open to suggestions - I may have also misunderstood what you sketched out @mcwhittemore and happy for any clarifications.

cc @kepta

kepta commented 7 years ago

( really sorry if this sidetracks the discussion of login. )

@batpad I agree with you and feel point 1 is the best. Although, I want point 1 minus the user/permission modal complexity.

If I were a malicious user I would simply login via OSM and then do malicious activity. The only thing stopping me would be a permission model (is this assumption correct ?) , which would allow certain ID's do certain (high risk) activities. From my experience of consuming osmcha and to-fix API's, I feel if we can avoid user table and the permission model altogether, it would keep things very simple and easy to understand.

Since we are doing less magic on the backend, I propose that we let the task creator decide what all users (whitelist/blacklist/all) can interact with the task she is going to create. And the backend can simply check every request and then either reject/accept depending on the white/black/all list of the task creator.

So how would backend know if a user belongs to a particular list?. We create a jwt out of user credentials and pass it to the user. Now whenever a user claims to see/edit a task X, we can see the payload of the JWT and allow/disallow the user.

Also we can have certain users be admin, who can be the owner of any task and hence delete/modify it. (hard coding the user names in the .env file / using data-team module for our private instance ?).

This is just a 💭 experiment and I might have overlooked some things. Do you guys think this is feasible?

mcwhittemore commented 7 years ago

@batpad @kepta and myself chatted offline, but to document that chat. Passing the auth from the frontend to the backend is a first pass solution. To solve the osm api can be slow problem we can wrap the api request to osm in mapbox/locking to get a quick in memory cache.

Long term, agree that number 1 is a good idea. My only concern is that it doesn't solve the robots making requests problem. But we can talk about that later.

batpad commented 7 years ago

We have user auth working - we can ticket out a next iteration plan separately - closing here.