Reputation: 2284
I have read a lot of different examples on how to implement authentication in an Angular app. I am using Firebase Simple Login as a (No-)Backend.
Users should only see any content of my app, once they are logged in. If they are logged out, all they can see is /auth/login
and /auth/register
. Currently, I have the following solution which works. But:
1) I am not sure whether this is bullet-proof because...
2) ... when I open /home
manually while NOT logged in, I correctly get redirected to /auth/login
but the HomeCtrl
gets executed anyway. No sensitive data is exposed because no data is returned from the Backend, but there must be a way to NOT execute the controller at all if I am logged out?
3) Everytime I expose sensitive data, do I have to check inside my controller if the user is authenticated over and over again?
Bonus question: How do I redirect to /home
after successful login? Currently, inside my AuthService I do $location.path('home');
on successful login, but this doesn't account for the state?!
My app.js:
angular.module('myApp', ['ionic', 'firebase', 'myApp.services', 'myApp.controllers'])
.run(function($rootScope, $location, AuthService) {
$rootScope.$on('$stateChangeStart', function (ev, to, toParams, from, fromParams) {
/**
* AuthService.isLoggedIn() returns TRUE or FALSE
* depending on whether user authenticated successfully
* against the Firebase backend
*/
// redirect to login
if (!AuthService.isLoggedIn() && to.name !== 'auth.register') {
$location.path('/auth/login');
}
});
})
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('auth', {
url: "/auth",
abstract: true,
templateUrl: "templates/auth-tabs.html",
controller: 'AuthCtrl'
})
.state('auth.login', {
url: '/login',
views: {
'login-tab': {
templateUrl: 'templates/auth-login.html'
}
}
})
.state('auth.register', {
url: '/register',
views: {
'register-tab': {
templateUrl: 'templates/auth-register.html'
}
}
})
.state('home', {
url: '/home',
templateUrl: 'templates/home.html',
controller: 'HomeCtrl'
});
$urlRouterProvider.otherwise('/home');
});
Upvotes: 2
Views: 763
Reputation: 3730
The way I've implemented it is by handling a 401
http server response, because I don't want to worry about checking for the user authentication state, I prefer letting the server handle that. That being said.
Documentation on $urlRouter.sync()
specifies that if you prevent the default event, you may manually trigger the succesChange
angular.module('app', ['ui.router']);
.run(function($rootScope, $urlRouter) {
$rootScope.$on('$locationChangeSuccess', function(evt) {
// Halt state change from even starting
evt.preventDefault();
// Perform custom logic
var meetsRequirement = ...
// Continue with the update and state transition if logic allows
if (meetsRequirement) $urlRouter.sync();
});
});
Upvotes: 1