I have an Angular app using UI Router where I'm trying to validate a user's token, if one exists, when the app runs. I am also checking that the user has permission to access certains routes. The problem is that $stateChangeStart
is running before I receive the response back from the authorization endpoint. Here's some code (coffeescript with js below) - this is all within my run
block.
app.run(($rootScope, $state, $stateParams, $log, Auth) ->
currentState = 'home'
$rootScope.$state = $state
# read a cookie if cookie exists
if Auth.setAuthenticationToken()
# hit api endpoint to validate token
Auth.validateToken (user) ->
# route to current state
# this returns after $stateChangeStart runs below
$state.go(currentState)
$rootScope.$on '$stateChangeStart', (event, toState, toParams, fromState, fromParams) ->
currentState = toState.name
Auth.setAuthenticationToken()
$rootScope.error = null
# compare users access permissions with incoming route's access level
if (!Auth.authorize toState.data.access, Auth.user)
event.preventDefault()
$rootScope.error = "Sorry, you haven't provided the required credentials."
$log.warn $rootScope.error
)
My question is how can I get the $stateChangeStart
to run only after the response from the auth endpoint has been returned. This only needs to happen the first time. Every subsequent state change can be done without hitting the auth endpoint.
The Auth0 Angular SDK decodes the ID token and emits its data through the auth. user$ Observable exposed by AuthService. Some of the ID token information includes the name, nickname, picture, and email of the logged-in user.
You can use the data from the ID token to personalize the user interface of your Angular application. The Auth0 Angular SDK decodes the ID token and emits its data through the auth. user$ Observable exposed by AuthService. Some of the ID token information includes the name, nickname, picture, and email of the logged-in user.
Then, Angular uses the Auth0 SDK to get an access token from Auth0 and attaches that access token as a bearer credential in the authorization header of the request. You then assign the result of the successful request to this. message, which you render in the user interface using a code box.
Requiring user login to access a route is easy: just include the canActivate property in the route definition and add AuthGuard as its value. When users who have not logged in visit that route, your Angular application will redirect them to the login page.
I'd create a function in your Auth
service that returns a promise. Later, resolve (authorized) or reject (not authrized) that deferred. Then use it on the resolve
property of your route definitions
$stateProvider.state('stateName',{
...
...
resolve: {
isAuthorized: function(Auth){
return Auth.checkAuthorization();
}
}
})
To support subsequent checks you could maintain a promise within the service This might look like:
myApp.service('Auth',function($http,$q){
var authStatusDeferred = $q.defer();
this.checkAuthorization = function(){
return authStatusDeferred.promise;
};
this.validateToken = function(user){
var isValid = false;
//..do validation stuff
if(isValid) authStatusDeferred.resolve();
//Otherwise state change will not happen..
};
});
oh, sorry about no coffee
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With