foundersandcoders / open-tourism-platform

An open platform to facilitate the creation of apps to promote local tourism and business in Nazareth
MIT License
17 stars 3 forks source link

initial OAuth set up #92

Closed m4v15 closed 7 years ago

m4v15 commented 7 years ago

ready for review.

@mattlub comments:


OLD comments:

DO NOT MERGE Not going to be ready for a while just trying out a few things

relates #93 #27

UPDATE from @mattlub: I've done a fair bit of work on this, see my comments below

mattlub commented 7 years ago

I've picked this up. Have refactored a fair bit.

Instructions on how to see what I've done: TODO (message me in the meantime)

I've been working with the following 3 links open: http://oauth2-server.readthedocs.io/en/latest/api/oauth2-server.html#oauth2server-token https://tech.zilverline.com/2017/03/17/nodejs-oauth2-provider https://github.com/slavab89/oauth2-server-example-mongodb

definitions:

user - user of the platform, a person, or 'resource owner' client- an app, owned by a user

reminder of the flow

routes:

GET /oauth/authorize

POST /oauth/authorize

POST /oauth/token

TODO:

mattlub commented 7 years ago

required views/endpoints:

more specifically, required endpoints:

des-des commented 7 years ago

Okay I have done some reading, and want to try and drop in a top level description of how this should all fit together.

In terms of authentication of requests made to the OTP API. A request can be authenticated in one of two ways.

  1. An app acting on behalf of a user will provide an authentication token. Here is an example of middleware that does this: https://github.com/oauthjs/express-oauth-server/blob/master/index.js#L42
  2. A user who is interacting directly with OTP, will provide a JWT, issued by us, this will be verified using the jwt secret and we will use the claims to extract the user data from the database.

Now, we number 2 basically set up. Creating the authentication token for part 1 is the (very) difficult part.

The module we are using will provide 3 methods, once we have configured it to properly interface with the database.

  1. authenticate: this will be used in our implementation of step 1 above
    1. Extract the authentication token from the authentication header
    2. retrieve the user who granted the token
    3. Check that the token has not expired
  2. Authorise: Here we accept a client_id from the body of a request and a redirect_url, authorise will generate a short lived authorisation code, which is embedded in the redirect. Here authorise is handling the response, so the user gets redirected without any further action on our part. @mattlub A user must be authenticated at this point.
  3. token. This handles a request that contains a client_secret, a client_id and an authorisation code. As far as I can see, this will handle the server response with a access token in the body.

So there is a kinda hidden step in here, that is not immediately obvious from looking at those three functions, but might be the missing piece in terms of understanding. Here is I think a key point https://github.com/oauthjs/node-oauth2-server/issues/264#issuecomment-193209294!

Basically, there are two steps in the granting of the authorisation code

  1. Login
  2. grant access

The second step here utilises the authorise function, with a custom authorisationFunction. There is another way to do this, but I do not understand it and it seems like passing a custom authorisationFunction makes more sense.

Here is an example: https://github.com/ubilogix/koa2-oauth-server/blob/master/examples/index.js#L273 with login redirecting back to grant page https://github.com/ubilogix/koa2-oauth-server/blob/master/examples/index.js#L226

Next steps

I see the best way forward being

  1. Set up a fake user in the database, create a custom authorisationFunction that assumes that user is logged in
  2. Finalise this pull with the above hack, without any of the views, just integration tests
  3. Update the other pull to use cookies instead of headers to store the session
  4. Once both pulls are together, update the authorisationFunction to make use of the session functionallity we have (see example above)
  5. Finally, we need to build the views, then move onto implementing the authentication layer in the app API.
mattlub commented 7 years ago

@des-des

Here is I think a key point https://github.com/oauthjs/node-oauth2-server/issues/264#issuecomment-193209294!

thanks, this was useful, flagging up similar things which were causing me problems, I think the module is just designed right now in a non-standard way.

I think we are on the same page now, more or less.


Next steps in my opinion:

des-des commented 7 years ago

@mattlub yup you are correct! But I see those things coming between point 3 and 4 above.

Ie now we know what we are doing, we need to find a way of moving stuff into master without merging everything together into one giant pull..

mattlub commented 7 years ago

@des-des yeh sorry, I hadn't seen your 'next steps' section when I wrote my comment. I'm good to start on your steps 1 and 2 tomorrow.

My comments/issues/things I'd like your opinion on:

  1. Do we store normal auth tokens in different table from OAuth access tokens? They are created in completely different flows, but could be the same model.
  2. how does the way we deal with authenticating requests from clients and users differ? In the simplest cases where apps have full permissions for users I guess there doesn't have to be much of a difference, but in more complicated cases I haven't really thought about it. I guess just middleware, which results in a scope object.
des-des commented 7 years ago

@mattlub

Clients will not authenticate.

A user can do 2 things:

  1. Create a app / client
  2. Grant a client permission to act on behalf of them (for mvp I think we will have only one scope, apps will not get granted super user scope, but will be able to do everything else the user can do)

Ie a super user might both these things, both allow another app to act on their behalf, but also create their own app (think github).

Not sure I am quite following you, but there will be 2 different ways to authenticate.

  1. We have header authorisation=bearer {oauthToken}
  2. I think we will move jwt we currently have into cookie,ie jwt in cookie (right now it is in header)

I do not think we need to store jwts right now, we can give them a 1h expiry time, and not store them on the server.

Lets chat about anything that does make sense tomorrow morning (sorry maybe kinda rambling)

des-des commented 7 years ago

@mattlub is this ready for me to look at again?

m4v15 commented 7 years ago

I think yes (from his gitter message) the only thing I questioned was adding the API mongoose models to their own folder and we weren't sure where the best place to put Authmodel.js cos it's not a mongoose model, but in the src folder seems a bit weird.

mattlub commented 7 years ago

@des-des yes has been for 2 days!