Meteor Iron-router server-side only route how to get the current user?
Asked Answered
T

2

8

For a server-only route, How can I get the current user.

Please note this is a route that looks like:

    this.route('report_access', {
      path: '/report/:humanId?/:reportKey',
      where: 'server',
      action: ....
   });

This is not in a publish or method call so Meteor.user() / Meteor.userId() fails.

I looked in the route.params and there is no userid set.

Tinny answered 23/4, 2014 at 18:39 Comment(2)
Why do you want to do this? When would a server-side route be called by a user that isn't a client?Extrusion
Lots of cases: 1) bookmarked urls, 2) 302 bounce redirects from external services, 3) or .... iron-router routes that are handled on the server onlyTinny
A
8

This works for me in 0.8:

if(this.request.cookies.meteor_login_token) u = Meteor.users.findOne({"services.resume.loginTokens.hashedToken": Accounts._hashLoginToken(this.request.cookies.meteor_login_token)});

I'm basically hashing the raw Meteor login token with the Accounts._hashLoginToken() function which allows for matching with the hashed token stored in the DB.

Atavistic answered 17/7, 2014 at 10:36 Comment(6)
Note that the cookie may not be available by default, at least in 0.9. To make the cookie available you can for example add meteorhacks:fast-render.Fairley
I'm trying to authenticate a user's request from a server side route, is there another way to make the cookie available without installing meteorhacks:fast-render (I'd like NOT to install yet another package just for this)?Domineering
@aaron meteorhacks:fast-render is a pretty essential package. I wouldn't worry about adding it.Fennelly
@MichaelCole sorry, but meteorhacks has basically closed down due to the founder/developer quitting meteor and going to the facebook stack. And it's not an essential package anyhow. Also, you should worry about adding any unsupported and undeveloped libs no matter the origin. Thanks.Domineering
@aaron, It's open source. It's ok to be sad that people move on, but not an excuse to complain they're not giving us free work. Step up.Fennelly
@MichaelCole not sad or complaining -- I just choose to not use it because I don't have the time or inclination to build my business software, and build out the tools that I use to build my business software. There's just too much choice.Domineering
V
6

You can't really do this on the server side without setting cookies on the client side when you log in.

Meteor stores the user's authentication token in localStorage which is not available at the HTTP header stage, only later after the page is loaded on client side javascript.

If you want to access the value in the headers in the manner like you are doing you would have to set a cookie when the user logs in with the user's token.

The users token is at localstorage/Meteor.loginToken & user Id at Meteor.userId().

Then check this value with the request header and find the token amongst the user's stored tokens in the users collection in mongodb at services.resume.loginToken.

There is a considerable security caveat to doing this because your loginToken is more exposed and could be used to get access to the account.

How does Meteor work with logins

Meteor establishes a DDP connection over websockets. When the web page has loaded with a previous 'saved' log in state, these loginTokens are read using javascript with the localstorage api. DDP is a communications layer over websockets or sockjs Meteor uses to communicate with the server.

The login occurs via the DDP protocol, after the javascript has loaded. This is the primary reason you can't do this directly with a server side route because you would not have access to DDP this way since Meteor's libraries are not available and no DDP connection is established at this point when the http request is sent.

Meteor's call & subscribe methods use this login to authenticate to publish methods on the server which all occurs on the DDP wire.

This answer should go into the specifics of how a login takes place: Authenticating with Meteor via DDP (and SRP?)

Vizza answered 23/4, 2014 at 19:14 Comment(9)
Pardon me: but this answer sounds incomplete. Clearly, Meteor.publish and Meteor methods know the current user. The server can't be forced to blindly trust the client. The server has to issue any login tokens and reconcile any HTTP request with a user.Tinny
@Tinny i've added a few details on how the Methods and the rest of Meteor works and authenticates itself & the more specifics on why this can't work on a plain route without cookies. I didn't include this initially because I thought you only wanted the answer to your specific use case instead of the specifics of the reasons why it is that way.Vizza
Hi - I don't see how using localstorage is some how more secure than using cookies. The token is on an untrustworthy client and can be leaked. The biggest issue with cookies is untrusted subdomains. That said, safari does not allow localstorage when in the private browsing mode anyhow - so Meteor has to have a non-localstorage failback mechanism to be reliable. Sigh. Looks like I will have to dive deep and hack a solution to what should be simple.Tinny
Your question has been asked at least several times. If you are not satisfied with @Akshat's answer, though it is very well explained, please take a look at this one, which shows a pretty easy solution that may help you solving your problem.Benoni
@apendua -- I am aware of that question. That question is about Meteor.method call. I am using a server-side only iron-router route. Two different beasts. If you have another suggested question, I would love to have the link.Tinny
First thing is: you shouldn't use iron-router for server side routes. It just not cool ;) I don't know what exactly you are trying to achieve here, but just in case you might be interested I am attaching a link to a sample project I was working on some time ago. It shows how to use tokens to authenticate user on a server-side route.Benoni
@Akshat - thanks for the references to the DDP. I will play with ddp-tools. And the pointer to which localStorage variable holds the loginToken. Popping it out to a cookie should be pretty easy and solve the problem.Tinny
@apendua- your comment is now really wrong ( github.com/EventedMind/iron-router/blob/devel/Guide.md ) - just like i knew it would be. Server-side routes are critical for many usecases including web hooks, and oauth authentication.Tinny
@apendua, we're all smart here, please pose harder.Fennelly

© 2022 - 2024 — McMap. All rights reserved.