I'm trying to get the basic Firebase authenticating to work with routers(ui-router) as in this example. For some reason I can't get this to work. It rejects me from going to any of the states and when I try to log the error in the run function it responses with this error.
Here is my code:
var app = angular.module('app', ['ui.router']);
app.run(["$rootScope", "$location", function($rootScope, $location) {
$rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) {
// We can catch the error thrown when the $requireSignIn promise is rejected
// and redirect the user back to the home page
if(error === "AUTH_REQUIRED") {
$state.go("home");
}
});
}]);
app.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider
.state('home', {
url: '/',
templateUrl: 'partials/home.html',
controller: 'mainController',
resolve: {
// controller will not be loaded until $waitForSignIn resolves
// Auth refers to our $firebaseAuth wrapper in the factory below
"currentAuth": ["Auth", function(Auth) {
// $waitForSignIn returns a promise so the resolve waits for it to complete
return Auth.$waitForSignIn();
}]
}
})
.state('create', {
url: '/create',
templateUrl: 'partials/create.html',
controller: 'createController',
resolve: {
// controller will not be loaded until $waitForSignIn resolves
// Auth refers to our $firebaseAuth wrapper in the factory below
"currentAuth": ["Auth", function(Auth) {
// $waitForSignIn returns a promise so the resolve waits for it to complete
return Auth.$waitForSignIn();
}]
}
})
.state('share', {
url: '/share',
templateUrl: 'partials/share.html',
controller: 'shareController',
resolve: {
// controller will not be loaded until $requireSignIn resolves
// Auth refers to our $firebaseAuth wrapper in the factory below
"currentAuth": ["Auth", function(Auth) {
// $requireSignIn returns a promise so the resolve waits for it to complete
// If the promise is rejected, it will throw a $stateChangeError (see above)
return Auth.$requireSignIn();
}]
}
});
$urlRouterProvider.otherwise('/');
});
app.factory("Auth", ["$firebaseAuth",
function($firebaseAuth) {
return $firebaseAuth();
}
]);
You're missing the firebase dependency:
var app = angular.module('app', ['ui.router', 'firebase']);
Related
I have a problem with my Auth.$requiredAuth()
.config(function($stateProvider, $urlRouterProvider){
$stateProvider.state('cursustext', {
url: '/cursustext',
templateUrl: 'views/cursustext/cursustext.html',
controller: 'cursustextCtrl',
resolved: {
"currentAuth": ["Auth", function(Auth){
return Auth.$requireAuth();
}]
}
})
})
-
.factory('Auth', function($firebaseAuth){
var auth = $firebaseAuth();
return auth;
})
Problem is: When I'm not logged in, I can still go to the page.
Does anyone know how to fix that?
Sincerely,
Jur
EDIT/UPDATE
angular.module('myApp.cursustext', ['ui.router'])
.run(["$rootScope", "$state", function($rootScope, $state) {
$rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) {
if (error === "AUTH_REQUIRED") {
$state.go('home');
}
});
}])
.config(function($stateProvider, $urlRouterProvider){
$stateProvider.state('cursustext', {
url: '/cursustext',
templateUrl: 'views/cursustext/cursustext.html',
controller: 'cursustextCtrl',
resolve: {
"currentAuth": ["Auth", function(Auth) {
return Auth.$requireSignIn();
}]
}
})
It works now. But when i'm not logged in, isn't redirect to home page. how?
typo here:
resolved: {
"currentAuth": ["Auth", function(Auth){
return Auth.$requireAuth();
}]
}
should be resolve
resolve: {
"currentAuth": ["Auth", function(Auth){
return Auth.$requireAuth();
}]
}
A resolve contains one or more dependency that must resolve successfully before the route will change, most likely this prevent the parser to force the resolution of the Auth dependency and that's why you can see the state without be logged.
EDIT:
to handle the case of error you can do this:
resolve: {
"currentAuth": ["Auth", function(Auth){
return Auth.$requireAuth().then(function(resp){
return resp;
})
.catch(function(err){
$location.path('/home'); //redirect to home page in case of error
})
}]
}
hey hope you fixed the issue, anyway i ran into the same problem
stateService.ts:525 Transition Rejection
I solved this by using older version of Angular Ui Router.
bower install angular-ui-router#0.3.1
The Latest Ui router had issues with Angularfire Auth example.
Cheers
I am trying to redrect user to login page if not auth my issue I cant see my code running if the user isnt auth,
userRoute.$inject = ['Router','$rootScope', '$state'];
function userRoute(Router,$rootScope,$state) {
$rootScope.$on("$stateChangeError", function (event, toState, toParams, fromState, fromParams, error) {
// We can catch the error thrown when the $requireSignIn promise is rejected
// and redirect the user back to the home page
debugger;
if (error === "AUTH_REQUIRED") {
$state.go("login");
}
});
and on my route I did:
controller: 'list.controler',
controllerAs: 'vm',
resolve: {
"firebaseUser": function (authService) {
// If the promise is rejected, it will throw a $stateChangeError
return authService.firebaseAuthObject.$requireSignIn();
}
}
});
Try:
$state.go("login"); //
.state("login", {
url:"/login",
controller: "loginCtrl",
templateUrl: "my/path/login.html"
})
Id advice you to use your moduleName.run() function in your js file whether is was app.js or another file name , it would be look like that :
//your moduleName and it's dependencies here
.run(["$rootScope", "$state", function($rootScope, $state) {
$rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) {
// We can catch the error thrown when the $requireSignIn promise is rejected
// and redirect the user back to the login page
if (error === "AUTH_REQUIRED") {
return $state.go("login");
}
});
}])
In your index.html
<script src=".../angular-ui-router.min.js"></script>
<script src=".../stateEvents.js"></script>
You'll need also to make a state for login, something like that :
.config(['$routeProvider', '$stateProvider', function($routeProvider, $stateProvider) {
$stateProvider.state('login', {
name: 'login',
url: '/login',
templateUrl: 'login/login.html',
controller: 'loginCtrl'
})
}])
I feel like this is really easy but I'm not sure why I can't figure it out.
For example if we want to restrict access to a page if a user is not logged in we can do something like:
// == LISTEN FOR ROUTE ERRORS
app.run(['$rootScope', '$location', function($rootScope, $location) {
$rootScope.$on('$routeChangeError', function(event, next, previous, error) {
if (error === 'AUTH_REQUIRED') {
$location.path('/login');
}
});
}]);
// == RETURN AUTH SERVICE
app.factory('Authentication', ['$firebaseAuth', function($firebaseAuth) {
return $firebaseAuth();
}]);
// == APP ROUTER
app.config(['$routeProvider', '$location', function($routeProvider, $location) {
$routeProvider
.when('/account', {
controller: 'userController',
templateUrl: 'views/account.html',
resolve: {
"currentAuth": ['Authentication', function(Authentication) {
return Authentication.$requireSignIn(); // if rejected throws $routeChangeError
}]
}
})
}]);
Now what if I want to add a resolve to the '/login' route so that if the user is logged in I can just force them to the account page or a success page?
.when('/login', {
controller: 'userController',
templateUrl: 'views/login.html',
resolve: {
"currentAuth": [function() {
// reject if the user is already logged in
}]
}
});
.when('/login', {
controller: 'userController',
templateUrl: 'views/login.html',
resolve: {
"currentAuth": ['$q', function($q) {
var p = $q.defer();
if (Authentication.$getAuth()) {
p.reject({code: someErrorCode, message: 'Already logged in'});
} else {
p.resolve();
}
return p.promise;
}]
}
});
You should also handle the scenario when logged in, in $routeChangeError or $stateChangeError
I'm using the AngularFire example for ui-router.
// for ui-router
app.run(["$rootScope", "$state", function($rootScope, $state) {
$rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) {
if (error === "AUTH_REQUIRED") {
$state.go("home");
}
});
}]);
app.config(["$stateProvider", function ($stateProvider) {
$stateProvider
.state("home", {
controller: "HomeCtrl",
templateUrl: "views/home.html",
resolve: {
"currentAuth": ["Auth", function(Auth) {
return Auth.$waitForAuth();
}]
}
})
.state("account", {
controller: "AccountCtrl",
templateUrl: "views/account.html",
resolve: {
"currentAuth": ["Auth", function(Auth) {
return Auth.$requireAuth();
}]
}
});
}]);
app.controller("HomeCtrl", ["currentAuth", function(currentAuth) {
}]);
app.controller("AccountCtrl", ["currentAuth", function(currentAuth) {
}]);
Everything works for the first user. The problem is that when the first user logs out and the second one logs in, the "currentAuth" still holds the first user's information. Why doesn't it get updated with the new login?
It actually gets updated if I refresh the page, but how can I load the new data without refreshing?
I am working with angular.js and satelizer to do JWT Authentication on a REST API.
The authentication works fine and the page is sending the authorization header within 3 states. Here is my state provider:
$stateProvider
.state('auth', {
url: '/auth',
templateUrl: '/views/login.html',
controller: 'AuthController as auth'
})
.state('dashboard', {
url: '/dashboard',
templateUrl: '/views/dashboard.html',
controller: 'DashboardController as dash'
})
.state('mitglieder', {
url: '/mitglieder',
templateUrl: '/views/mitglieder.html',
controller: 'MitgliederController as mitglieder'
})
.state('neuesMitglied', {
url: '/neuesMitglied',
templateUrl: '/views/neuesMitglied.html',
controller: 'NewMitgliederController as newMitglied'
})
.state('users', {
url: '/users',
templateUrl: '/views/main.html',
controller: 'UserController as user'
});
});
But however, inside the state 'neuesMitglied' it suddenly does no longer send the authorization header and gets rejected by the rest api. My NewMitgliederController looks like this:
(function() {
'use strict';
angular
.module('authApp')
.controller('NewMitgliederController', NewMitgliederController);
function NewMitgliederController($auth, $state, $http, $rootScope, $scope) {
var vm = this;
vm.error;
//vm.toAdd;
//vm.rawImage;
//Fetched Data
vm.fetchedData;
var fetchData = function() {
$http.get('APIv1/Beitragsgruppen/list/').success(function (data) {
vm.fetchedData.mitgliedsgruppen = data;
}).error(function (error) {
vm.error = error;
});
}
angular.element(document).ready( function(){
$('#mainNav ul, #mainNav li').removeClass('active');
$('#mitgliederNav').addClass('active');
fetchData();
} );
}
})();
Why is it not working inside this controller but in all other controllers, the $http.get ist working with authorization header?
EDIT
I tracked this behavior a little bit and found that something is removing the "Authorization" Header which has been set by the satellizer interceptor (for this controller request the method is fired and this header is really added by satellizer interceptor but it is getting removed afterwards and I dont't know where because I do not touch any header data or have own interceptors)... Is it a bug?
Try this one:
(function() {
'use strict';
angular
.module('authApp')
.controller('NewMitgliederController', NewMitgliederController);
function NewMitgliederController($http, $scope) {
var vm = this;
vm.error = {};
vm.fetchedData = {};
fetchData();
function fetchData() {
$http.get('APIv1/Beitragsgruppen/list/').then( function(res) {
vm.fetchedData.mitgliedsgruppen = res;
$('#mainNav ul, #mainNav li').removeClass('active');
$('#mitgliederNav').addClass('active');
}, function(err) {
vm.error = err;
});
}
}
})();