Meteor.user() on iron-router server side
Asked Answered
A

2

9

How can check, on server side route, if user is logged?

I would add check on 'before', but Metor.user() don't work here.

thanks in advance.

p.s. I have found How to get Meteor.user() to return on the server side?, but not work on iron-router

Adamec answered 26/11, 2013 at 14:19 Comment(1)
I was trying to get this working, as well, but didn't. I ended up writing a Meteor method instead. This is not ideal, but at least in my case it was a viable solution to my problem.Thingumajig
C
8

I'm afraid that this is not possible. I guess that the problem comes from the fact that you're trying to connect to the server with two different protocols - both literally and in logically - so there is no obvious way to relate this two actions.

There is, however, a pretty simple solution that may suit your needs. You'll need to develop a simple system of privileges tokens, or secret keys, or whatever you call them. First, create a server method

var Secrets = new Meteor.Collection("secrets"); // only on server!!!

Meteor.methods({
  getSecretKey: function () {
    if (!this.userId)
      // check if the user has privileges
      throw Meteor.Error(403);
    return Secrets.insert({_id: Random.id(), user: this.userId});
  },
});

Then, you can now use it on the client to get the secretKey which attach to your AJAX request (or something), either within the HTTP header or in the URL itself. Fear not! They will all be encrypted if you're using HTTPS.

On the server side you can now retrieve the secretKey from the incoming request and check if it is present in the Secrets collection. You'll know then if the user is granted certain privileges or not. Also you may want to remove your secret keys from the collection after some time for safety reasons.

Chauvinism answered 27/11, 2013 at 0:49 Comment(7)
Thanks for explain and solutionAdamec
In your example here: github.com/apendua/meteor-uploader/blob/master/server.js it seems you're using connectHandlers for server side route. Would you still recommend this approach for server side routes? I'm using Iron Router, and would like to see if your approach would fit in with what you're doing with tokens.Indispensable
Also, I noticed your solution (in the link) does not contain a database to store the tokens or the expiration of tokens, can you provide a example of this?Indispensable
Specifically on the client, can you provide an example of how to attach the secretKey to the HTTP header (or URL)?Indispensable
Please see my SO question along these lines: #27734610Indispensable
The key part of the uploader is connect.multipart() middleware and I am not 100% sure if you can simply use it with IronRouter. I saw the answer to your question and I think the method based on cookies proposed by Akshat is really nice.Chauvinism
@Indispensable Check out my answer below for an example where the token is accessed from the Mongo collectionRinghals
R
3

If what you're looking to do is to authenticate the Meteor.user making the request, I'm currently doing this within the context of IronRouter.route(). The request must be made with a valid user ID and auth token in the header. I call this function from within Router.route(), which then gives me access to this.user:

###
  Verify the request is being made by an actively logged in user
  @context: IronRouter.Router.route()
###
authenticate = ->
  # Get the auth info from header
  userId = this.request.headers['x-user-id']
  loginToken = this.request.headers['x-auth-token']

  # Get the user from the database
  if userId and loginToken
    user = Meteor.users.findOne {'_id': userId, 'services.resume.loginTokens.token': loginToken}

  # Return an error if the login token does not match any belonging to the user
  if not user
    respond.call this, {success: false, message: "You must be logged in to do this."}, 401

  # Attach the user to the context so they can be accessed at this.user within route
  this.user = user

  ###
    Respond to an HTTP request
    @context: IronRouter.Router.route()
  ###
  respond = (body, statusCode=200, headers={'Content-Type':'text/json'}) ->
    this.response.writeHead statusCode, headers
    this.response.write(JSON.stringify(body))
    this.response.end()

This code was heavily inspired by RestStop and RestStop2. It's part of a meteor package for writing REST APIs in Meteor 0.9.0+ (built on top of Iron Router). You can check out the complete source code here:

https://github.com/krose72205/meteor-restivus

Ringhals answered 7/1, 2015 at 22:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.