I am a newbee in angular and I would like to know how to make a AuthenticationService where I would check if user is authenticated or not. I have routes for which I want a user to be authenticated in order to be able to see them, and if they are not authenticated that they are redirected to login page. I am using satellizer for token based authentication.
This is my app.js
angular.module('coop', ['ionic', 'coop.controllers', 'coop.services', 'satellizer'])
.constant('ApiEndpoint', {
url: 'http://coop.app/api'
})
.run(function($ionicPlatform, $rootScope, $auth, $state, $location) {
// Check for login status when changing page URL
$rootScope.$on('$routeChangeStart', function (event, next) {
var currentRoute = next.$$route;
if (!currentRoute || currentRoute.requiresAuth && !AuthenticationService.authenticated) {
$location.path('/auth');
}
else if (!currentRoute || !currentRoute.requiresAuth && AuthenticationService.authenticated) {
$location.path('/front');
}
});
$rootScope.logout = function() {
$auth.logout().then(function() {
// Remove the authenticated user from local storage
localStorage.removeItem('user');
// Remove the current user info from rootscope
$rootScope.currentUser = null;
$state.go('main.auth');
});
}
$rootScope.token = localStorage.getItem('token');
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
// StatusBar.styleDefault();
StatusBar.show();
StatusBar.overlaysWebView(false);
StatusBar.styleLightContent();
StatusBar.backgroundColorByHexString("#2a2e34");
}
});
})
.config(function($stateProvider, $urlRouterProvider, $authProvider, ApiEndpoint) {
$authProvider.loginUrl = ApiEndpoint.url + '/authenticate';
$stateProvider
.state('main', {
url: '/main',
abstract: true,
templateUrl: 'templates/main.html',
requiresAuth: true
})
.state('main.auth', {
url: '/auth',
views: {
'content': {
templateUrl: 'templates/login.html',
controller: 'AuthController',
requiresAuth: false
}
}
})
.state('main.front', {
url: '/front',
views: {
'content': {
templateUrl: 'templates/main-front.html',
controller: 'FrontPageController',
requiresAuth: true
}
}
})
.state('main.article', {
url: '/article/{id}',
views: {
'content': {
templateUrl: 'templates/main-article.html',
controller: 'ArticleController',
requiresAuth: true
}
}
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/main/front');
});
And my controllers:
angular.module('coop.controllers', [])
.controller('FrontPageController', function($scope, ArticleService, $state) {
ArticleService.all().then(function(data){
$scope.articles = data;
$scope.like = function(article){
article.like = article.like == 0 ? 1 : 0;
ArticleService.like(article.id, article.like)
};
})
})
.controller('ArticleController', function($scope, ArticleService, $stateParams, $ionicSlideBoxDelegate, $auth) {
ArticleService.get($stateParams.id).then(function(response) {
$scope.article = response;
$scope.commentsCount = response.comments.length;
$scope.articleText = response.text;
$scope.like = function(){
$scope.article.like = $scope.article.like == 0 ? 1 : 0;
ArticleService.like($scope.article.id, $scope.article.like)
};
$ionicSlideBoxDelegate.update();
})
})
.controller('AuthController', function($scope, $location, $stateParams, $ionicHistory, $http, $state, $auth, $rootScope) {
$scope.loginData = {}
$scope.loginError = false;
$scope.loginErrorText;
$scope.login = function() {
var credentials = {
email: $scope.loginData.email,
password: $scope.loginData.password
}
$auth.login(credentials).then(function(response) {
var token = JSON.stringify();
localStorage.setItem('token', response.data.token);
$ionicHistory.nextViewOptions({
disableBack: true
});
$state.go('main.front');
}, function(){
$scope.loginError = true;
$scope.loginErrorText = error.data.error;
});
}
});
Updated code
I have changed the app.js as suggested:
// Check for login status when changing page URL
$rootScope.$on('$routeChangeStart', function (event, next) {
var currentRoute = next.$$route;
if (!currentRoute || currentRoute.requiresAuth && !$auth.isAuthenticated()) {
$location.path('/main/login');
}
else if (!currentRoute || !currentRoute.requiresAuth && $auth.isAuthenticated()) {
$location.path('/main/front');
}
});
And have added logout controller to delete user and token from localstorage, but I am still not being redirected to login page:
My controller:
.controller('AuthController', function($scope, $location, $stateParams, $ionicHistory, $http, $state, $auth, $rootScope) {
$scope.loginData = {}
$scope.loginError = false;
$scope.loginErrorText;
$scope.login = function() {
var credentials = {
email: $scope.loginData.email,
password: $scope.loginData.password
}
$auth.login(credentials).then(function(response) {
var token = JSON.stringify();
localStorage.setItem('token', response.data.token);
$ionicHistory.nextViewOptions({
disableBack: true
});
$state.go('main.front');
}, function(){
$scope.loginError = true;
$scope.loginErrorText = error.data.error;
});
}
$scope.logout = function() {
$auth.logout().then(function() {
// Remove the authenticated user from local storage
localStorage.removeItem('user');
localStorage.removeItem('token');
// Remove the current user info from rootscope
$rootScope.currentUser = null;
$state.go('main.login');
});
}
});
If you are using satellizer, it already takes care of this for you.
Use the isAuthenticated() method of satelizer's $auth service instead of defining your own
$rootScope.$on('$routeChangeStart', function (event, next) {
var currentRoute = next.$$route;
if (!currentRoute || currentRoute.requiresAuth && !$auth.isAuthenticated()) {
$location.path('/auth');
}
else if (!currentRoute || !currentRoute.requiresAuth && $auth.isAuthenticated()) {
$location.path('/front');
}
});
Basically what $auth.isAuthenticated() does is checking if the user has a vaild jwt saved, and returns true or false.
The $routeChangeStart handler kicks in in every route change, checks if the route has requiresAuth set and if isAuthenticated returns true or false and acts accordingly.
If you want to do it on your own, here is a good tutorial on how to decode the token and check if it's valid:
https://thinkster.io/angularjs-jwt-auth
Related
Hi after setting up Spring Security, the login works fin for me.But when I refresh anypage it redirects me to login page. How Can I get rid of this.
Here is my code
config.js
'use strict';
var app = angular.module('MyApp', [ 'ngResource', 'ngRoute',
'myAppControllers', 'ngAnimate', 'ui.bootstrap', 'ngCookies' ]);
app.config(function($routeProvider) {
$routeProvider.when('/products/:idCat', {
templateUrl : '../views/partials/products.html',
controller : 'ProductsController'
}).when('/products', {
templateUrl : '../views/partials/allProducts.html',
controller : 'ProductsController'
}).when('/supprimer', {
templateUrl : '../views/partials/delete.html',
}).when('/update', {
templateUrl : '../views/partials/update.html',
controller : 'UserController'
}).when('/client', {
templateUrl : '../views/partials/client.html',
controller : 'ClientController'
}).when('/agences', {
templateUrl : '../views/partials/agences.html',
controller : 'MapController'
}).when('/login', {
templateUrl : '../views/partials/login.html',
controller : 'mainController'
}).when('/', {
templateUrl : '../views/partials/Home.html',
})
$routeProvider.otherwise('/');
});
app.run(function($route, $rootScope, $http, $location, $cookieStore,
$anchorScroll) {
$rootScope.authenticated = false;
$rootScope.$on('$routeChangeStart', function() {
var originalPath = $location.url();
if ($rootScope.authenticated == false) {
$location.path('/login');
} else {
$rootScope.redirectUrl = angular.copy($location.url());
var user = $cookieStore.get('user');
if (user !== undefined) {
$rootScope.user = user;
$http.defaults.headers.common['X-Auth-Token'] = user.token;
$location.url(originalPath);}})
});
my app.js where I have my controller ang call for authenticate Service
myAppControllers
.controller(
'mainController',
function($scope, $rootScope, loginService, ProductService,
$location, $cookies, $cookieStore, $http) {
$rootScope.salesAgent = true;
$scope.loggedIn = false;
$rootScope.hasRole = function(role) {
if ($rootScope.user === undefined) {
return false;
}
if ($rootScope.user.authorities === undefined) {
return false;
}
for (var i = 0; i < $rootScope.user.authorities.length; i++) {
if ($rootScope.user.authorities[i].authority == role)
return true;
}
return false;
};
$scope.logout = function() {
console.log("Testtttttttttt");
delete $rootScope.user;
delete $http.defaults.headers.common['X-Auth-Token'];
$cookieStore.remove('user');
$location.url("/login");
};
$scope.authenticate = function() {
loginService
.authenticate($scope.username,
$scope.password)
.then(
function(user) {
$rootScope.user = user;
$http.defaults.headers.common['X-Auth-Token'] = user.token;
$cookieStore.put('user',
user);
if ($rootScope.redirectUrl != null
&& $rootScope.redirectUrl
.indexOf('/') == -1)
$location
.url($rootScope.redirectUrl);
else {
$rootScope.authenticated = true;
$location.path("/");
}
$rootScope.redirectUrl = null;
$rootScope.redirectStatus = null;
}),
function err(data) {
if ($rootScope.redirectStatus == 401)
}
};});
I'll be pleased for your help!
You are storing authenticated value in $rootScope after refreshing it is getting nullified, instead of that use $cookieStore for angular 1.2 or less, or $cookies for angular 1.2 or above.
You are using $cookieStore for user, do the same for authenticated
$cookieStore.put('authenticated',$rootScope.authenticated);
Check if the cookie exists as a first step in run
app.run(function($route, $rootScope, $http, $location, $cookieStore, $anchorScroll) {
var user = $cookieStore.get('user');
if (user !== undefined) {
// set up X- header and other variables here
Another option is to store the authentication value in the localStorage:
localStorage.setItem ('session.authenticated', true);
Then you can get the authentication value as follows:
localStorage.getItem("session.authenticated") || false;
I'm trying to DRY in $stateProvider and prevent adding the same auth function in each resolve. I've created decorator that in each state change would add this function to current state, but auth function isn't invoked, How to fix it or how to workaround discussed issue?
app.config(function ($stateProvider, $urlRouterProvider, $provide) {
$provide.decorator('$state', function($delegate, $rootScope) {
$rootScope.$on('$stateChangeStart', function(event, state, params) {
if ($delegate.current === "login" || $delegate.current === "register") {
return;
}
console.log("decorator", $delegate);
$delegate.current.resolve = {
auth: ['AuthService', '$stateParams', function(AuthService, $stateParams) {
//how to invoke this function?
if (AuthService.isAuthenticated()) {
return AuthService.me(); //promise
} else {
return false;
}
}]
};
});
return $delegate;
});
states definition:
$stateProvider.state('root', {
abstract: true,
url: '/',
views: {
"": {
controller: 'RootCtrl',
templateUrl: 'views/root.html'
},
"header#root": {
templateUrl: 'views/header.html'
}
}
})
.state('root.home', {
url: urlPrefix,
views: {
"content#artworks": {
templateUrl: 'views/home.html',
//resolve: {
// auth: ['AuthService', '$stateParams', function(AuthService, $stateParams) {
// }]
//}
}
}
})
...
If I understand your requirement correctly, we can use native UI-Router built-in decorator:
decorator(name, func)
Allows you to extend (carefully) or override (at your own peril) the stateBuilder object used internally by $stateProvider. This can be used to add custom functionality to ui-router, for example inferring templateUrl based on the state name... (read more in the doc)
There is a working plunker
So, we can have this var auth
var auth = ['AuthService', '$stateParams',
function(AuthService, $stateParams) {
//how to invoke this function on needed states?
if (AuthService.isAuthenticated()) {
return AuthService.me();
} else {
return false;
}
}
];
And here we just use decorator with some "IF" logic
.config(['$stateProvider',
function($stateProvider) {
$stateProvider.decorator('views', function(state, parent) {
var result = {},
views = parent(state);
// some naive example when to not inject resolve
if (state.name === "home") {
return views;
}
// child already has that in parent
if (state.name.indexOf(".") > 0) {
return views;
}
angular.forEach(views, function(config, name) {
// here inject the resolve (if not existing)
config.resolve = config.resolve || {};
// and extend it with the auth stuff above
config.resolve.auth = auth;
result[name] = config;
});
return result;
});
}
])
And later few our states, which will be extended by the above stuff
$stateProvider
.state('home', {
url: "/home",
templateUrl: 'tpl.html',
})
.state('parent', {
url: "/parent",
templateUrl: 'tpl.html',
controller: 'SharedCtrl',
})
.state('parent.child', {
url: "/child",
templateUrl: 'tpl.html',
controller: 'SharedCtrl',
});
Check it in action here
I realized that $delegate.current object contains only raw stateProvider config data. To wrap resolve function I add my function to $delegate.$current on each state change.
$provide.decorator('$state', function($delegate, $rootScope) {
$rootScope.$on('$stateChangeStart', function(event, state, params) {
if ($delegate.current === "err404" || $delegate.current === "login" || $delegate.current === "register") {
return;
}
console.log("decorator", $delegate);
$delegate.$current.resolve["auth"] = ['AuthService', '$stateParams', function(AuthService, $stateParams) {
if (AuthService.isAuthenticated()) {
console.log('AuthService.me()');
return AuthService.me();
} else {
return false;
}
}]
});
return $delegate;
});
Update
I found related discussion on github, you can add universal resolve function into toState param:
app.run(['$rootScope', '$state',
function($rootScope, $state) {
$rootScope.$on('$stateChangeStart', function(event, toState) {
if (toState.name === "login" || toState.name === "register") {
return;
}
toState["resolve"]["auth"] = ['AuthService', '$stateParams', function(AuthService, $stateParams) {
if (AuthService.isAuthenticated()) {
return AuthService.me();
} else {
return false;
}
}];
});
}
]);
I am trying to get a header to update after login. I have used both $on and $watch in this effort to no avail. When I refresh it works correctly. Code is as follows below.
header.html (missing excess nav bar code for simplicity)
<li><a ng-href="#/login" ng-hide="showMenu">Login</a></li>
<li><a ng-href="#/signup" ng-hide="showMenu">Signup</a></li>
<li>Logout</li>
app.js
$stateProvider
.state('app', {
url: '',
views: {
'header': {
templateUrl: 'views/partials/_header.html',
controller: 'HeaderCtrl'
}
}
})
header.js (The broadcast fires correctly as demonstrated by the console.logs)
angular.module('urbinsight')
.controller('HeaderCtrl', function ($scope, $rootScope, $state, $location, UserAuthFactory, AuthFactory) {
$scope.logout = function () {
UserAuthFactory.logout();
$rootScope.$broadcast('loginStateChange');
$location.path('/');
};
$scope.showMenu = AuthFactory.loggedStatus();
$rootScope.$on('loginStateChange', function(){
console.log($scope.showMenu)
$scope.showMenu = AuthFactory.loggedStatus();
console.log($scope.showMenu)
})
})
authService
angular.module('urbinsight.services')
.factory('AuthFactory', function ($window) {
var isLogged = false;
return {
check: function() {
if ($window.sessionStorage.token && $window.sessionStorage.user) {
isLogged = true;
} else {
isLogged = false;
delete this.user;
}
},
loggedStatus: function() {
return isLogged;
},
changeLoggedStatus: function() {
isLogged = !(isLogged);
}
};
})
login function + broadcast
login.submit = function () {
var username = user.username,
password = user.password;
if (username !== undefined && password !== undefined) {
UserAuthFactory.login(username, password).success(function(data) {
$rootScope.showMenu = true
// AuthFactory.isLogged = true;
AuthFactory.changeLoggedStatus();
AuthFactory.user = data.user.username;
AuthFactory.userRole = data.user.role;
$rootScope.$broadcast('loginStateChange');
$window.sessionStorage.token = data.token;
$window.sessionStorage.user = data.user.username;
$window.sessionStorage.userRole = data.user.role;
$location.path('/');
}).error(function(status) {
$window.alert('Oops something went wrong!');
});
} else {
$window.alert('Invalid credentials');
}
};
Please tell me what I am doing wrong.
You have set the "$rootScope.showMenu = true" in your login controller. But in your header controller you also have "$scope.showMenu = AuthFactory.loggedStatus();"
So i would remove this line from your header controller
$scope.showMenu = AuthFactory.loggedStatus();
Since you want your header html to react to $rootscope showMenu variable directly
I have an angular project set up that when a user goes to /cloud and they aren't logged in (isLoggedIn() return fails), it redirect to /login. And then if they are logged in and go to /login it redirects them back to /cloud.
However, when I click the logout button to clear the local storage, I get the following error (everything still works):
Error: null is not an object (evaluating 'a.$current.locals[l]')
According to my logs, it appears to be happening on the onEnter for my logout controller.
I'm new to angular so any advice or guidance would be greatly appreciated.
var routerApp = angular.module('myapp', ['ui.router'])
//config for state changes
.factory('Auth', function($http, $state, $q) {
var factory = { isLoggedIn: isLoggedIn };
return factory;
function isLoggedIn(token) {
return $http.post('/auth/session', {token:token});
}
})
.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/cloud');
var authenticated = ['$q', 'Auth', '$rootScope', function ($q, Auth, $rootScope) {
var deferred = $q.defer();
if (typeof window.localStorage['authtoken'] === 'undefined') {
var authtoken = undefined;
} else {
var authtoken = window.localStorage['authtoken'];
}
Auth.isLoggedIn(authtoken).then(function() {
deferred.resolve();
}, function() {
deferred.reject();
});
return deferred.promise;
}];
var authGuest = ['$q', 'Auth', '$rootScope', function ($q, Auth, $rootScope) {
var deferred = $q.defer();
if (typeof window.localStorage['authtoken'] === 'undefined') {
var authtoken = undefined;
} else {
var authtoken = window.localStorage['authtoken'];
}
Auth.isLoggedIn(authtoken).then(function() {
deferred.reject();
}, function() {
deferred.resolve();
});
return deferred.promise;
}];
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'pages/templates/login.html',
resolve: { authenticated: authGuest }
})
.state('logout', { url: '/logout', onEnter: function($state) { localStorage.clear(); $state.go('login'); } })
.state('cloud', {
url: '/cloud',
templateUrl: 'pages/templates/cloud.html',
resolve: { authenticated: authenticated }
})
})
.run(function ($rootScope, $state) {
$rootScope.$on('$stateChangeError', function (event, from, error) {
if(from.name == "login") {
$state.go('cloud');
} else {
$state.go('login');
}
});
});
The problem seems to be here:
var authenticated = ['$q', 'Auth', '$rootScope', function ($q, Auth, $rootScope) {
var deferred = $q.defer();
if (typeof window.localStorage['authtoken'] === 'undefined') {
var authtoken = undefined;
} else {
var authtoken = window.localStorage['authtoken'];
}
Auth.isLoggedIn(authtoken).then(function() {
deferred.resolve();
}, function() {
deferred.reject();
});
return deferred.promise;
}];
This function will only run once on Configuration. The promise, once resolved, will continue to resolve to same value regardless of LocalStorage. Every time you
resolve: { authenticated: authenticated }
You will get back the authenticated value at Configuration step.
instead, add a controller to define functions to request status for each type
.controller('AuthenticationController', function($scope, '$q', Auth, '$rootScope') {
$scope.authenticated = function () {
var deferred = $q.defer();
if (typeof window.localStorage['authtoken'] === 'undefined') {
var authtoken = undefined;
} else {
var authtoken = window.localStorage['authtoken'];
}
Auth.isLoggedIn(authtoken).then(function() {
deferred.resolve();
}, function() {
deferred.reject();
});
return deferred.promise;
};
$scope.authGuest = function ($scope, '$q', Auth, '$rootScope') {
....
return deferred.promise;
};
});
Then, in your routing configurations:
.state('login', {
url: '/login',
templateUrl: 'pages/templates/login.html',
controller: 'AuthenticationController'
resolve: { authenticated: $scope.authGuest() }
})
.state('cloud', {
url: '/cloud',
templateUrl: 'pages/templates/cloud.html',
resolve: { authenticated: $scope.authenticated()}
})
Now, each time you be resolving a fresh promise.
Disclaimer: Without a working version to use, I formed this code for demonstration purposes. It should be treated a pseudo-code to lead in right direction.
I am trying to use resolve to check for the authentication state and direct the user to the appropriate view.
I am trying the following (see below), but it does not result in transferring to the appropriate states as it would have done when refreshing the page.
app.js
// Ionic Starter App
// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', 'starter.controllers', 'firebase'])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})
.run(["$rootScope", "$state", function($rootScope, $state) {
$rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) {
// We can catch the error thrown when the $requireAuth promise is rejected
// and redirect the user back to the home page
if (error === "AUTH_REQUIRED") {
console.log('stateChangeError')
$state.go("app.login");
}
});
}])
.config(function($stateProvider, $urlRouterProvider) {
var authResolve = {
authReturn: function($state, $q, $timeout, Auth) {
var defer = $q.defer();
var ref = Auth.refObj();
ref.onAuth(authDataCallback)
function authDataCallback(authData) {
if (authData) {
console.log("authDataCallback: User " + authData.uid + " is logged in with " + authData.provider);
defer.resolve(authData)
} else {
console.log("authDataCallback: User is logged out");
defer.reject('AUTH_REQUIRED')
}
}
$timeout(function() { // See: http://stackoverflow.com/q/24945731/247243
defer.reject('login');
}, 250);
return defer.promise;
}
};
$stateProvider
.state('app', {
url: "/app",
abstract: true,
templateUrl: "templates/menu.html",
controller: 'AppCtrl'
})
.state('app.login', {
url: "/login",
views: {
'menuContent': {
templateUrl: "templates/login.html",
controller: "LoginCtrl"
}
}
})
.state('app.profile', {
url: "/profile",
views: {
'menuContent': {
templateUrl: "templates/profile.html",
resolve: authResolve
}
}
})
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/app/login'); //CHANGE TO HOME
});
controller.js
angular.module('starter.controllers', [])
.controller('AppCtrl', function($scope) {
})
.controller('LoginCtrl', function($scope, $timeout, $state, Auth) {
var ref = Auth.refObj();
var authData = ref.getAuth();
if (authData) {
console.log("User " + authData.uid + " is logged in with " + authData.provider);
$scope.authData = authData;
} else {
console.log("User is logged out");
}
$scope.signOut = function() {
Auth.signOut();
}
$scope.signIn = function() {
Auth.signIn();
}
})
.factory('Auth', function($firebase, $firebaseAuth, $state) {
// Register the callback to be fired every time auth state changes
var ref = new Firebase("https://lovin.firebaseio.com");
var signIn = function() {
ref.authWithPassword({
email : 'sa.ibisevic#gmail.com',
password : 'Maserati2014'
}, authHandler);
// logging users in
function authHandler(error, authData) {
if (error) {
console.log("Login Failed!", error);
$state.go("app.login")
} else {
console.log("Authenticated successfully with payload:", authData);
$state.go("app.profile")
}
}
}
var signOut = function() {
ref.unauth();
$state.go("app.login")
}
var authRef = function() {
return $firebaseAuth(ref);
}
return {
signIn: signIn,
signOut: signOut,
refObj: function() {
return ref;
},
authRef: authRef
}
})
login.html
<ion-view view-title="Login">
<ion-nav-bar class="bar-stable">
<ion-nav-buttons side="left">
<button class="button button-icon button-clear ion-navicon" menu-toggle="left">
</button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-content>
<h1>{{authData.uid}}</h1>
<button class="button" ng-click="signIn()">Sign In</button>
<button class="button" ng-click="signOut()">Sign Out</button>
</ion-content>
</ion-view>
Beware that you can listen to the authentication state on the $firebaseSimpleLogin object. So you could do something like that:
$rootScope.$on('$firebaseSimpleLogin:logout', function(event) {
$state.go('login');
});
Hope this helps.