Sunday, 19 February 2017

How to wait for authentication check before loading default state in angularjs applicaton with ui-router

I have an angularjs application that is using $transitions to check if a user is authenticated before certain $state changes. I am using passport.js to do the authentication strategy. If authentication has not occurred or fails the AuthisLoggedIn() check I want the user to be reverted back to the 'login' state. The issue I am having is that the default state '/' always seems to load before my authentication promise, Auth.getCurrentUserAsync() is done executing causing a bunch of issues. How can I enforce that no state gets loaded while waiting for this authentication check and then send the user to my 'login' state if they in all cases when they are not authenticated. My code is as follows




app.js



clientApp.run(['$transitions', '$state', '$http', 'Auth', '$rootScope',
function($transitions, $state, $http, Auth, $rootScope) {
$http.defaults.xsrfHeaderName = 'X-CSRFToken'
$http.defaults.xsrfCookieName = 'csrftoken'


$rootScope.baseApiUrl='/app/api'


//verify the user
$transitions.onStart(
{
to: function(state) {
if (typeof state.authenticate !== 'undefined' && state.authenticate === false) {
return // this state does not require authentication
}
if (!Auth.isLoggedIn()) {

Auth.getCurrentUserAsync().then(

function() {
if (!Auth.isLoggedIn()) {
$state.go('login')
}
}
)
}
}
})
}])





clientApp.config(['$urlRouterProvider', '$stateProvider', '$locationProvider',
function($urlRouterProvider, $stateProvider, $locationProvider) {
$urlRouterProvider
.otherwise('/')
$stateProvider
.state('main', {

url: '/',
component: 'main',
authenticate: true
})
.state('login', {
url: '/login',
template: loginTemplate,
controller: 'LoginCtrl',
controllerAs: 'Login',
authenticate: false,

params: {
loginMessage: "",
loginErrorMessage: "",
username: "",
password: undefined,
errors: []
},
})
$locationProvider.html5Mode(true)
}])





auth.js



import angular from 'angular'

angular
.module('app.factories.auth', [])

.factory('Auth',
['$http', '$q', '$rootScope',
function Auth($http, $q, $rootScope) {

function _isLoggedIn() {
if (Object.keys(authObj.user).length !== 0) {
return true
} else {
return false
}

}

function _login(user) {
const deferred = $q.defer()

$http.post($rootScope.baseApiUrl + '/user/login', {
username: user.username,
password: user.password
})
.then(

function(response) {
if (response.status === 200) {
authObj.user = response.data.user
deferred.resolve(response)
} else {
authObj.user = {}
deferred.reject(response)
}
},
function(err) {

authObj.user = {}
deferred.reject(err)
}
)

return deferred.promise
}


function _getCurrentUserAsync() {

return $http.get($rootScope.baseApiUrl + '/user/status')
.then(
function(response) {
console.log('response', response)
if (response.data.status) {
authObj.user = response.data.user
} else {
authObj.user = {}
}
},

function() {
authObj.user = {}
})
}

const authObj = {
isLoggedIn: _isLoggedIn,
getCurrentUserAsync: _getCurrentUserAsync,
login: _login,
user: {}

}

return authObj
}
])

No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...