1

I am starting with Polymer and Firebase and have implemented the Google OAuth authentication.

I have notice the page loads before authentication and if you click back you can get to the page without authorization, albeit that you are not able to use the firebase api and therefore the page is not usable.

My issue is that I do not want my javascript loaded until authenticated.

How could this be done.

Many thanks

Jay Byford-Rew
  • 5,736
  • 1
  • 35
  • 36
  • Without seeing the minimal code that reproduces your problem it will be impossible to help. See http://stackoverflow.com/help/mcve – Frank van Puffelen Jan 27 '16 at 15:26
  • Any simple polymer/firebase implementation would reproduce the issue. i.e. following this tutorial https://codelabs.developers.google.com/codelabs/polymer-firebase/index.html?index=..%2F..%2Fpolymer-summit&viewga=UA-39334307-12#0 Here is my test implementation – Jay Byford-Rew Jan 27 '16 at 15:42

4 Answers4

2

It depends if your using firebase or their polymer wrapper, polymerfire.

Create a document for all the imports that you want to be conditionally loaded

// user-scripts-lazy.html
<link rel="import" href="user-script-one.html">
<script src="script.js"></script>
// etc

Using Polymerfire In the element that hosts <firebase-auth> create a observer and you'll expose some variables from firebase-auth.

<firebase-auth
     user="{{user}}" 
     status-known="{{statusKnown}}"></firebase-auth>

In the observer, watch the user element and the status known

statusKnown: When true, login status can be determined by checking user property

user: The currently-authenticated user with user-related metadata. See the firebase.User documentation for the spec.

observers:[
'_userStateKnown(user, statusKnown)'
]

_userStateKnown: function(user, status) {
 if(status && user) {
  // The status is known and the user has logged in
  // so load the files here - using the lazy load method
  var resolvedPageUrl = this.resolveUrl('user-scripts-lazy.html.html');
  this.importHref(resolvedPageUrl, null, this.onError, true);
 }
}

To get the state without using polymerfire you can use onAuthStateChange

properties: {
  user: {
    type: Object,
    value: null // important to initialise to null
  }
}

..

ready: function() {
 firebase.auth().onAuthStateChagned(function(user) {
  if(user) 
    this.set('user', user); // when a user is logged in set their firebase user variable to ser
  else 
    this.set('user', false); // when no user is logged in set user to false


 }.bind(this)); // bind the Polymer scope to the onAuthStateChanged function 
}

// set an observer in the element
observers: [
 '_userChanged(user)'
],

_userChanged: function(user) {
 if(user === null) {
  // authStatus is false, the authStateChagned function hasn't returned yet. Do nothing
  return;
 }
 if(user) {
  // user has been signed in
  // lazy load the same as before
 } else {
  // no user is signed in
 }
}

I haven't tested the code while writing it here, but i've implemented the same thing various times.

Community
  • 1
  • 1
Snewedon
  • 2,410
  • 2
  • 13
  • 27
  • Many thanks, this is more like it ... but is it possible for a person to go into developer tools (F12) and just execute these two lines? var resolvedPageUrl = this.resolveUrl('user-scripts-lazy.html.html'); this.importHref(resolvedPageUrl, null, this.onError, true); – Jay Byford-Rew Nov 04 '16 at 09:49
  • Yeah you could do that - in general any data is javascript should be ok to show any user. I don't think any actual security should be done by JavaScript any more. It should all be done via the server - with firebase security rules. If you want to "hide some code" to none members set up a server and a endpoint, authenticate with it via firebase custom auth and only return some code when the user is logged in. Firebase Hosting its self is static so you can't do that with them - try app engine - But security by obscurity is not good practice. – Snewedon Nov 04 '16 at 18:45
  • You could store the URL for the hidden code in firebase database - protect it so only the users you want can access that bit of data and then resolve that - then none users don't have access to a easy to read `path = 'somepath';` line – Snewedon Nov 04 '16 at 18:45
1

There are a couple of options.

  1. Put content you don't want loaded behind a dom-if template with "[[user]]" as its driver. This could include your firebase element, so the database isn't even considered until after log on.
  2. Put a modal dialog box up if the user is not logged on. I do this with a custom session element . Whilst the overlay is showing then the rest of the page is unresponsive to anything.
akc42
  • 4,893
  • 5
  • 41
  • 60
  • I don't want any discover-able content until authenticated. I assume [[user]] is only a switch, the content is still downloaded prior to the check. This is not what I want. Thanks anyhow. – Jay Byford-Rew Feb 09 '16 at 08:36
  • Polymer doesn't load the content behind an element with a dom-if template protecting it until the if resolves to true for the first time. So there will be no content to display until that resolves. User is an Object Property of your app which a session manager can set to something when the user has logged on. How does that not meet your needs? – akc42 Feb 09 '16 at 11:16
  • This may be so but the content is still downloaded whether it is displayed or not. I do not want my content downloaded until authenticated. 'Downloaded' is different to 'displayed' – Jay Byford-Rew Feb 15 '16 at 08:50
0

If it is simply an aesthetic issue of removing the non-logged-in page from view, could you either hide the page (or display some kind of overlay) while the user isn't authenticated?

I currently have this in an current project for some elements: hidden$="{{!user}}"

RedBassett
  • 3,469
  • 3
  • 32
  • 56
  • 1
    No not aesthetic issue, actually stop most content but I understand that there is no server side component to Firebase apart form the database which means redirect to other page if not authenticated is probably not an option without content first coming down the browser. – Jay Byford-Rew Jan 29 '16 at 09:58
  • @kernowcode did you find a solution? I can't believe that this is a problem however, I am having the same issue right now :D – Niklas Dec 07 '16 at 16:45
  • 1
    I have just added my answer now possible due to Firebase Storage a new addition different from the realtime database. – Jay Byford-Rew Dec 07 '16 at 16:58
0

I have identified the solution for my purpose ...

  1. Add storage role based authorization (see is there a way to authenticate user role in firebase storage rules?)
    • This does have a limitation currently of hard coded uid's
  2. In the page, request storage resource and if successful include it in the dom (i.e. add script element with src pointing to storage url)
  3. Call javascript as normal
Community
  • 1
  • 1
Jay Byford-Rew
  • 5,736
  • 1
  • 35
  • 36