Protecting Routes in a Polymer Starter Kit App

294 views Asked by At

I'm using the Polymer Starter Kit and polymerfire to create a firebase app with two routes: 'staff' and 'donate'. The donate route is public and the staff route is private. I'd like to protect the staff route such that only logged in users who have an email ending with mycompany.com can access it. Unauthenticated users will be redirected to /donate.

My first attempt was to wrap links to and declarations of those routes in dom-if templates. This works to prevent users from seeing the route, but if a user is logged in, they will not be able to navigate to that route from the address bar - they'll have to click on a link to the route in the app first. This is confusing: the address bar may still say 'staff' even though the 'donate' page is shown.

<iron-selector selected="[[page]]" attr-for-selected="name" class="drawer-list" role="navigation">
  <template is="dom-if" if="[[user]]" restamp="true">
    <a name="staff" href="/staff">Staff</a>
  </template>
  <a name="donate" href="/donate">Donate</a>
</iron-selector>

<iron-pages
    selected="[[page]]"
    attr-for-selected="name"
    fallback-selection="donate"
    role="main">
  <template is="dom-if" if="[[user]]" restamp="true">
    <ksybf-staff name="staff"></ksybf-staff>
  </template>
  <ksybf-donate name="donate" route="[[subroute]]"></ksybf-donate>
</iron-pages>

I've also tried imperatively preventing route loading:

_routePageChanged: function(page) {
  if (this.user) {
    this.page = page || 'donate';
  } else {
    this.page = 'donate';
  }
},

This produces similar results: initial browsing to /staff loads the 'donate' route, even though the address bar shows //app/staff.

How can I protect routes in a way which just works from the user's perspective?

2

There are 2 answers

1
FTM On BEST ANSWER
  1. Add an id to your <iron-pages>.
  2. Add a iron-select listener to it.
  3. Inside the listener function, add the logic to redirect in case the user is not logged in.

It would look like this: For the <iron-pages>:

<iron-pages
    id="selector"
    selected="[[page]]"
    attr-for-selected="name"
    fallback-selection="donate"
    role="main">
  <ksybf-staff name="staff"></ksybf-staff>
  <ksybf-donate name="donate" route="[[subroute]]"></ksybf-donate>
</iron-pages>

Add the listener:

listeners: {
    'selector.iron-select': 'pageChanged'
}

And the function:

pageChanged: function(e){
    var page = this.$.selector.selected;
    switch (page){
        case 'staff':
            if (userIsNotLoggedIn){
                //Ideally, I would send a toast here saying that the user should be logged in
                window.location.href = '/donate'                
            }
    }
}
0
edje On

How I approach this is to utilise the "selected-attribute" of iron-pages.

<iron-pages selected-attribute="active">

This will set the active attribute in your staff and donate pages. Use an observer on the active attribute in your staff component and if active === true then do your check. If they aren't authenticated/authorized then just kick them back to where they belong.