Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using standard bearer token auth in Restivus #129

Closed
awatson1978 opened this issue Aug 20, 2015 · 8 comments
Closed

Using standard bearer token auth in Restivus #129

awatson1978 opened this issue Aug 20, 2015 · 8 comments

Comments

@awatson1978
Copy link

Hi there!
Thanks for taking the time to put Restivus together! This is fantastic!

So, hey... we're working on a package that implements the HL7 Argonaut FHIR spec, and the first implementation sprint has a requirement that involves implementing an auth token using the following HTTP Authorization header:

Authorization: Bearer {server-specific-token-here}

Any chance you could recommend how to implement this using Restivus? I got the rest of the spec worked out; but I'm a little unsure of how one would implement a custom HTTP Authorization header with Restivus.

The Clinical/Healthcare Working Group has a bunch of members who are requesting this HL7 functionality, and it's going to get used in all sorts of neat applications: teleradiology viewers, genetic analysis of pediatric cancer patients, personalized medicine dispensaries, health information exchanges, healthcare marketplaces, etc.

Any help you might be able to give will be going to a good cause!
Thanks,
Abigail

@kahmali
Copy link
Owner

kahmali commented Aug 20, 2015

Hi Abigail!

First and foremost, I just want to say a huge THANK YOU to you for all your awesome contributions to Meteor and its community. The cookbook was a great resource when I was first getting started with Meteor and had no idea which way to turn, and you've even answered random emails from a friend of mine that really helped steer us in the right direction on a few issues in the past. So thanks for all of that, and everything else you do to help make the Meteor community one of the best out there!

Okay, that being said, I certainly want to do anything I can to return the favor. I'm sorry that the documentation on custom authentication is insufficient. This is probably as good a time as ever to clean that up.

Do you need an OAuth provider (to generate and persist a token), or are you just looking to use the bearer token standard to authorize a user/account that has already authenticated by some other means? I, shamefully, have very limited experience with OAuth, so I would need to do some further research to see what solutions are out there for implementing a custom OAuth provider in Meteor.

If you're using an existing OAuth provider (or not using OAuth at all) and you'll already have the token stored on the server, then there is a way to do this with Restivus' custom auth. There are three steps to implementing this in Restivus, all of which must take place in the custom auth function:

  1. Parse the bearer token
  2. Validate the bearer token (find the user/account with that token)
  3. Return the authorized user/account

1. Parsing the bearer token

Restivus does not provide an out-of-the-box solution for parsing a bearer token. If you already have code to do this, then you can skip ahead to the next step. If you don't, there's a (currently unpublished) Connect middleware package for parsing a standard bearer token. Any route that it is added to will have this.request.authToken set to the parsed token.

Since Restivus is built on top of simple:json-routes, you can add middleware using JsonRoutes.addMiddleWare(). Since the middleware package exposes its middleware function as JsonRoutes.Middleware.parseBearerToken, you can use

JsonRoutes.addMiddleWare('api/path', JsonRoutes.Middleware.parseBearerToken);

where 'api/path' is the route path where the middleware will be added. To add the middleware to all routes, just exclude the path (you probably already know this from working with Connect in the past).

2. Validating the bearer token

This is pretty straightforward. Grab the bearer token you parsed in the previous step and handle any validation steps you deem necessary. For most folks this will probably amount to simply querying the user/account collection where the bearer token is stored (probably the Meteor.users collection, but nothing is stopping you from using a different collection). If the token exists, it's considered validated. Of course, you can provide additional validation steps, such as hashing a token, or maybe validating a time stamp to check for its expiration. That's all up to your specific requirements.

If validating against a hashed bearer token stored in the default location in a Meteor.user document, you can use this (also currently unpublished) middleware package.

3. Return the authorized user/account

Once you consider the token validated, you just need to return the user/account document that it belongs to as {user: <user_document>}. That document will be available in any authenticated endpoints as this.user, with its Mongo ID available as this.userId.

Putting that all together should look something like:

CoffeeScript (I'll convert this to JS at your request)
JsonRoutes.addMiddleWare 'api/path', JsonRoutes.Middleware.parseBearerToken
Api = new Restivus
  useDefaultAuth: false
  auth:
    user: ->
      authToken = this.request.authToken
      user = Meteor.users.findOne {'path.to.token': authToken}
      user: user

Not as bad as it sounded up above, I think :)

Hopefully, that's a good start. Of course, there are some planned features for Restivus that will make this even better. Namely, improved support for middleware integration, allowing middleware to be added directly to Restivus routes/endpoints, for hassle-free, finer-grained control over middleware behaviors. My goal for v0.9 is to separate Restivus "core" and move all the extra functionality into add-on packages (e.g., collections support) and middleware (e.g., auth, error handling, before/on/after hooks, etc).

Additionally, I'll see if we can go ahead and get those middleware packages published, along with the other updates that have been lingering on simple:rest. It's been a while, so I'm not quite sure what was preventing us from publishing everything. I'll have to coordinate with @stubailo and @aldeed on that. I'll try my very best to take care of it by this weekend, or at the very least get the ball rolling on it.

Please let me know if you need me to clarify anything, or if you need any additional information at all. Hopefully, this can be a start to my effort to repay you for all your great contributions to the community. Thanks so much, and keep up the awesome work!

@stubailo
Copy link
Contributor

Yeah I've been lagging on publishing that stuff. But I have published the new version of simple:json-routes with all of the new stuff. I guess we should publish the middleware packages as well.

@kahmali
Copy link
Owner

kahmali commented Aug 20, 2015

Thanks for the speedy response, Sashko!

Sounds great. Let me know if there's anything I can do to help.

@awatson1978
Copy link
Author

Hi Kahmali :)
I really appreciate that. Thank you. They say no good deed goes unpunished; and you might be surprised at the amount of crap I deal with on a regular basis for being so active in the community. (Or maybe you wouldn't be surprised at all, and would understand exactly what I'm talking about.) Regardless, it always means a lot to hear those stories, and know that other people are finding the Cookbook and other projects I'm working on to be helpful.

Anyhow. Awesome response. Thank you! Thank you! I think this should get me up and running with something. I'm very excited to give this a try with the middleware components.

My apologies for the delay in response... I've had a client emergency this past week regarding a HIPAA audit. Also, I'm getting ready to drive out to Santa Cruz, and It will be another couple of weeks before I can implement. I'm looking at the week of Sept 15th before I can do another HL7/Rest sprint. But this is very much on my roadmap, and I'll get a response on how it integrates, and some documentation in a few weeks.

Regarding your question of OAuth... it's in the HL7 Argonaut spec. So, yes. We would very much like to eventually get an OAuth2 server incorporated.

The good news is that we've got financial resources from UC Santa Cruz, four or five Meteor startups willing to help with it; and the resources of some big players like Epic and Cerner willing to help with externalized testing. We're planning development sprints over the next few months; and want to put together an entire OAuth2 server reference implementation as part of the HL7 spec.

So, I may very well ping you with occasional questions over the next few months, if it's okay. And any thoughts you have on OAuth2 server integration... I'd be more than happy to have a conversation here, on the meteor forums, a hackpad, or elsewhere.

Thank you again for your wonderful reply! :)

@ccsavvy
Copy link

ccsavvy commented Sep 24, 2015

Hi Kahmali,

Good day.

I'm new to developing an API and I found out your art work ~ "Restivus". Currently, I'm using it to my API development with Meteor. It's pretty dope man! Thanks!! Right now, I'm creating a custom login authentication as per my company requires, that all request are in http body request which is now giving me a headache on how to implement because its not following the standard that is already built in with meteor accounts.

My main goal is to reuse/override the authentication that is already on meteor.
Can you please convert this coffeescript to javascript?

JsonRoutes.addMiddleWare 'api/path', JsonRoutes.Middleware.parseBearerToken
Api = new Restivus
useDefaultAuth: false
auth:
user: ->
authToken = this.request.authToken
user = Meteor.users.findOne {'path.to.token': authToken}
user: user

Once again, thank you!

Best Regards,
Christian

@a4xrbj1
Copy link

a4xrbj1 commented Sep 24, 2015

Use http://js2.coffee/ for translating it

Andreas

@ccsavvy
Copy link

ccsavvy commented Sep 24, 2015

Hi, thanks for the quick response. Anyway, I've already converted it when I Googled it.
The next question is how to do about it after converting, when running it gives me these error:

TypeError: Cannot read property 'handle' of undefined
W20150924-21:52:12.096(8)? (STDERR) at Function.app.use (/Users/user/.meteor/packages/simple_json-routes/.1.0.4.8tkp64++os+web.browser+web.cordova/npm/node_modules/connect/lib/proto.js:69:30)

@kahmali kahmali changed the title Authorization: Bearer {server-specific-token-here} Using standard bearer token auth in Restivus Sep 24, 2015
@kahmali
Copy link
Owner

kahmali commented Sep 24, 2015

Thanks for the tip @a4xrbj1!

Hi @LshanuNearKheel. Thanks so much for the kind words!! Can you do me a favor and open a new issue if you're experiencing problems. It appears Abigail (the author of the original issue) was able to successfully implement bearer token auth with the steps provided here. There's no need to bug her with our messages since this is an unrelated issue. I'm actually going to close this issue, since it's intended purpose has been fulfilled.

Also, please read the extremely short section from my Contributing Guidelines on reporting bugs (I can almost assure you this isn't a bug, but rather just something off about your code, no disrespect). If you need help debugging your code, that may be a better question for Stack Overflow, or the Meteor forums. I'm so insanely busy trying to launch an MVP right now that writing this message is pretty much all the time I have to spend on Restivus today. Only about 20 people see these Issues, but 100s will see your SO question, so you just have a better chance of getting a quick response, possibly from a few different people. Same for the Meteor forums.

I wish I could be more help. If you run into a wall on SO and the Meteor forums, just come back here (well, not exactly here, but in a new issue) and let me know, and we'll definitely get this figured out for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants