Redirect to Requested Page after Login with Firebase Auth

Good evening,

Firebase comes with a sweet Authentication system – Top to Down, referred to as the Firebase Auth! Hands down!

What we will be doing in this short guide is how to redirect a user to a requested page after login, assuming the requested page is user protected.

Check out madewithfirebase.com – a site showcasing applications powered by Firebase, including itself!

If you have played with Firebase’s Auth system, you probably are aware of the fact that, Firebase (AngularFire to be precise) comes with a $waitForSignIn and a $requireSignIn functions with allows you to enforce a user gets to a URL if and only if they’re authenticated. Before we get into the details….

Depending on how big our app is, and how long it takes to get from one place to the other, it can be very useful sending your visitor to the page they were on before they were brought to the login page.

The page could be hidden deep down somewhere on your site, where you don’t want your visitor to walk that path again.

In standard AngularJS Authentication using a REST endpoint, redirecting to current page after login is a pretty standard process, and pretty much well known and implemented. A simple Google search reveals the code snippet to accomplish that functionality.

To put things into perspective, this is how redirecting user to requested page after login can be achieved, considering the assumptions made inline this code snippet:

.config([ ... {
     .state('profile', {
        ....,
        access: true
        ....
 });
}])

// assumption 1: AuthService is an authentication service connected to a REST endpoing
// with the function isAuthenticated(), which returns either true or false
.run(function($rootScope, $state, AuthService, $location) {
  // thanks to http://stackoverflow.com/a/27792642/1757321
  var afterLogIn;
  $rootScope.$on('$stateChangeStart', function(event, next, current) {
    if (!AuthService.isAuthenticated() && next.access) {
      console.log(next.name);
      afterLogIn = $location.path();
      $location.path('/login').replace();
      $state.go('login');
    } else if (afterLogIn && AuthService.isAuthenticated()) {
      $location.path(afterLogIn).replace();
      afterLogIn = null;
    }
  });
});

I won’t be explaining the above snippet that much, because, well, I assume you know what it is. If not, check the SO link attached.

What I found out was that trying to use a similar approach above with Firebase Auth promises always didn’t work as I expected.

And so, I settled on using this approach for the redirect.

// URL config state
    .state('admin', {
      url: '/admin',
      templateUrl: 'admin/admin.html',
      controller: 'AdminController',
      resolve: {
        currentAuth: ['Auth', function(Auth) {
          // if not logged in, emits an event called "AUTH_REQUIRED"
          // we trap that event in a jiffy
          return Auth.$requireSignIn()
        }],
        $title: function() {
          return 'Admin';
        }
      },
      restricted: true
    })

Then, moving down to our .run function, I proceeded as such:

    $rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) {
      if (error === "AUTH_REQUIRED") {
        // pass in some params to the login $state, with the requested
        // state within the toWhere value
        $state.go('login', { toWhere: toState });
      }
    });

The last step is that, within your login route, you catch the passed in $stateParams and redirect to that state after login succeeds, like so:

Auth.$signInWithEmailAndPassword($scope.formData.email, $scope.formData.password)
  .then(function(firebaseUser) {
    // if rootscope is set
    if ($stateParams.toWhere != null) {
      $state.go($stateParams.toWhere.name);
    } else {
      $state.go('home');
    }

  })
  .catch(function(error) {
    // handle errors here
  })

This approach might not be scalable enough. The use of interceptors might be the best way to handle this automatically for you.

However, I hope you found the approach above straightforward enough to use in your simple app.

Thanks.

 

Exit mobile version