0

It seems that in Meteor, we cannot call a server side route to render a file to the page without some sort of work-around from our normal workflow in terms of authentication.

Software/Versions

I'm using the latest Iron Router 1.* and Meteor 1.* and to begin, I'm just using accounts-password.

Background/Context

I have an onBeforeAction that simply redirects the user to either the welcome page or home page base upon if the user is logged in or not:

both/routes.js

if (Meteor.isClient) {
Router.onBeforeAction(function () {
  if (!Meteor.user() || Meteor.loggingIn())
    this.redirect('welcome.view');
  else
    this.next();
  }
  ,{except: 'welcome.view'}
);

Router.onBeforeAction(function () {
  if (Meteor.user())
    this.redirect('home.view');
  else
    this.next();
  }
  ,{only: 'welcome.view'}
);
}

In the same file, both/routes.js, I have a simple server side route that renders a pdf to the screen:

Router.route('/pdf-server', function() {
  var filePath = process.env.PWD + "/server/.files/users/test.pdf";
  console.log(filePath);
  var fs = Npm.require('fs');
  var data = fs.readFileSync(filePath);
  this.response.write(data);
  this.response.end();
}, {where: 'server'});

Cookie related code added

I found a SO answer where a method to set and get the cookies is outlined here: SO Cookies technique

And then added the following code to my project: client/main.js

Deps.autorun(function() {
    if(Accounts.loginServicesConfigured() && Meteor.userId()) {
        setCookie("meteor_userid",Meteor.userId(),30);
        setCookie("meteor_logintoken",localStorage.getItem("Meteor.loginToken"),30);
    }
}); 

But this does not work as expected, the setCookie code is not valid for some reason.

My Questions

Question 1: Using cookies, how do I properly set/get and check for the cookies? Question 2: What precautions should I take using the cookies approach?

Side Question: Is cookies the best way to go about this, or is there a simpler way to achieve the same thing?

Community
  • 1
  • 1
Aaron
  • 3,068
  • 2
  • 21
  • 44
  • 1
    I can't tinker and test this right now, but [here's documentation on how to set cookies in the browser](https://developer.mozilla.org/en-US/docs/Web/API/document.cookie) and [here's an NPM module for working with cookies](https://github.com/pillarjs/cookies). The basic idea is to set the user id and login token as you've tried, and then check them against the user record in MongoDB in the server-side route. – sbking Jan 01 '15 at 17:48
  • Thank you. I'll have a read and look at the documents and package. – Aaron Jan 02 '15 at 03:56
  • For precautions, check out this blog post by MDG - [Why Meteor doesn't use session cookies](http://info.meteor.com/blog/session-cookies) – xamfoo Jul 02 '15 at 05:30
  • Thanks. Also, from that article, 'We will likely use cookies to implement server-side rendering; when you visit a Meteor app at foo.com that renders templates on the server, it needs to know who you are so that it can render the templates with your data in it. The only way for the very first HTTP request to foo.com to know who you are? A cookie set on a previous visit to foo.com!' – Aaron Jul 02 '15 at 10:10

1 Answers1

1

You can call a method that generates a temporary access token and when you get a positive answer from the server (meaning that the token was created), you can check the validity of this token before loading the PDF.

As for using cookies: It might be more convenient when compared to calling a method, waiting and then redirect/open a new tab. I tested your code, with the W3C client side javascript functions, and it worked at client side. The function getCookie assume that you're the client, not the server. You need to check the request and extract the cookies.

Mário
  • 1,603
  • 14
  • 24
  • Sorry, I'm confused. You mean call a Meteor.method, from where? How would the token be temporary, and how do you generate one? check the validity of this token, generated in the Meteor.method, in the Iron Router route? You can call Meteor.methods on server side routes? – Aaron Jan 02 '15 at 03:55
  • You can create a server method the would generate a token and you store it in mongodb. On your server route, you simply query for this token and check the validity (1 hour expiration). – Mário Jan 02 '15 at 14:52