Has anyone implemented the redirect to login then redirect to requested URL pattern with Iron Router?

This is a fairly common pattern and seems it should be straightforward to implement with Iron Router:

  1. Existing (but logged out) user hits a route/URL in the the app.
  2. Redirect the user to the login to have them authenticate, then…
  3. After successful authentication, redirect them to the originally requested URL

Has anyone implemented this pattern with Iron Router?

Is it simpler than I imagine?

Chris

I’ve done it by storing the current URL as a session variable, and then including a Router.go() call to the value of that variable when the login is successful. I don’t know if that’s the best way to do it with Iron Router though.

1 Like

It is in fact very simple and you have to think in meteor terms so forget about the redirect and url storing etc.

Taken from the first example at https://github.com/iron-meteor/iron-router/blob/devel/Guide.md#hooks

Router.onBeforeAction(function () {
// all properties available in the route function
// are also available here such as this.params

  if (!Meteor.userId()) {
    // if the user is not logged in, render the Login template
    this.render('Login');
  } else {
    // otherwise don't hold up the rest of hooks or our route/action function
    // from running
    this.next();
  }
});

The URL’s in a typical request/response over http get/post paradigm makes use of URL’s in server roundtrips.

But with a reactive client side router paradigm, a url is just like any other reactive variable that you can handle. In our case, change what is displayed on the page. In other terms render the “page” or the “login form”.

Thanks. You’re right. I wasn’t thinking about this in the Meteoric way. That nailed it. Seems that old habits die hard sometimes. Thanks.

1 Like

In my case, if they hit any URL without being logged in, I want to kick them back to the welcome page. If/when they log in, I kick them to the home page (so I can control where they start). I don’t want them going to a random page without hitting home first and navigating from there. But my site is an application and not a informational site.

I use this:

if (Meteor.isClient) {
  var requireLogin = function() {
    if (! Meteor.user()) {
      if (Meteor.loggingIn()) {
        Router.go('dashboard.view');
        this.next();
      } else {
        Router.go('welcome.view');
        this.next();
      }
    } else {
      this.next();
    }
  }
  Router.onBeforeAction(requireLogin);
}

The reason I use Router.go instead of this.render is because using Router.go allowed me to use a different template for the layout. this.render worked too, but would not change the layout template, even though I had it defined in the route under layoutTemplate

Router.route('/dashboard', {name: 'dashboard.view', layoutTemplate: 'dashboard_layout', template: 'dashboard_main'});
Router.route('/welcome', {name: 'welcome.view', layoutTemplate: 'welcome_layout', template: 'welcome'});.
1 Like

I did this in my main layout template:

{{#if loggedInUser}}
  {{> navbar}}
  {{> yield}}
{{else}}
  {{> customLogin}}
{{/if}} 

And I’m using a custom written login system that will set a session variable when the user has successfully logged in, and clear it when they log out… so loggedInUser is a helper on the layout template:

Template.layout.helpers({
    loggedInUser: function () {
      return Session.get('loggedInUser');
    }
  });

The customLogin template displays the form for username and password, and as soon as the reactive session variable “loggedInUser” is set, the template will switch from showing the customLogin template to showing the navbar template and then the yield shows whatever else I am trying to show for the particular route.

2 Likes

yes that’s a common pattern. this package provides an easy way to handle all account ui stuff