Losing authentication after refreshing the page (AngularJS, NodeJS) - angularjs

So I have authentication for my web app. This is my authentication controller.
myTodoList.controller('authController', function($scope, $rootScope, $http, $location) {
$scope.user = { username: '', password: '' };
$scope.error_message = '';
$scope.login = function() {
$http.post('/auth/login', $scope.user).success(function(data) {
if (data.state == 'success') {
$rootScope.authenticated = true;
$rootScope.current_user = data.user.username;
$location.path('/app');
} else {
$scope.error_message = data.message;
}
});
};
$scope.register = function() {
$http.post('/auth/signup', $scope.user).success(function(data) {
if (data.state == 'success') {
$rootScope.authenticated = true;
$rootScope.current_user = data.user.username;
$location.path('/app');
} else {
$scope.error_message = data.message;
}
});
};
});
This works fine, I get my authentication after logging in or making a new registration. But After refreshing the page I lose my authentication. I think these lines generate the problem.
var myTodoList = angular.module("myTodoList", ['ngRoute', 'ngResource']).run(function($http, $rootScope) {
$rootScope.authenticated = false;
$rootScope.current_user = 'Guest';
$rootScope.signout = function() {
$http.get('auth/signout');
$rootScope.authenticated = false;
$rootScope.current_user = 'Guest';
};
});
At the top of my maincontroller.js I have this $rootScope.authenticated = false; line. This is needed I know but this could be the line that says it should be false instead of true after refreshing. What should I do to get around this problem?

Instead of storing the data on the rootScope, store it in the sessionStorage instead - this will persist across refreshes
https://github.com/gsklee/ngStorage

Related

Getting Error: [$injector:unpr] error in angularjs but i have added my dependencies correcty?

this is how my factory looks like
app.factory('AuthenticationService',['$http', function ($http, $localStorage) {
var AuthenticationService = {};
var api = 'http://del1-vm-kohls:8080/Survey' ;
AuthenticationService.Login = function(username,password,callback){
$http.post('http://del1-vm-kohls:8080/Survey/user/login',{userId: username, password: password})
.success(function(response){
if(response.token) {
// storing token in localstorage if user refreshes
$localStorage.currentUser = {userId : username , token: response.token };
// adding token of authentication for futher use in getting data
authentication.token = response.token;
callback(true);
}
else{
callback(false);
}
});
}
AuthenticationService.getSurvey = function(token){
}
return AuthenticationService;
}]);
this is how my controller looks like
var app = angular.module('myApp',[]);
app.controller('myCtrl', ['$scope', '$localStorage', '$http', 'AuthenticationService', function($scope, $localStorage, $http, AuthenticationService){
$scope.username = "";
$scope.password = "";
$scope.login = false;
$scope.checkLogin = function(){
AuthenticationService.Login($scope.username, $scope.password, function(result){
if(result === true)
{
console.login("Logindone");
$scope.login = true;
$localStorage.setItem('auth', 'true');
location.href = "../../application/content/index.html";
}
else{
$scope.login = false;
$localStorage.setItem('auth', 'false');
sweetAlert("", "Invalid Username or Password", "error");
}
});
}
}]);
You are missing $localStorage in factory dependency declaration.
It should be like :
app.factory('AuthenticationService',['$http','$localStorage', function ($http, $localStorage) {

How to do automatic login in angular js?

i have a login screen and i am doing login by using some hard cord data.
angular.module('starter.controllers', [])
.controller('AppCtrl', function($scope, $rootScope, $window, $ionicModal, $timeout, authService, $state, $http, $ionicLoading, $location) {
//$window.location.reload();
$scope.loginSubmitted = false;
$scope.myflag = false;
$scope.User = {};
$scope.toast = function() {
$ionicLoading.show({
template: 'wrong credentials'
});
$timeout(function() {
$ionicLoading.hide();
}, 1000);
}
$scope.footerflag = true;
$scope.hidefooter = function() {
$timeout(function() {
$scope.footerflag = false;
},1)
}
$scope.showfooter = function() {
$timeout(function() {
$scope.footerflag = true;
},1)
}
$scope.doLogin = function() {
console.log("trying login");
// // var res = $http.post('http://login.com/postLogin', $scope.user);
// authService.postdetails($scope.User).success(function(data, status, headers, config) {
// $scope.message = data;
// console.log("succesfn");
// console.log(status);
//
// })
// .error(function(data, status, headers, config) {
// alert("failure message: " + JSON.stringify({
// data: data
// }));
// console.log(fail);
// });
$scope.loginSubmitted = true;
$scope.loginstatus = 0;
authService.GetByUsername().success(function(data) {
$scope.UserData = data;
// console.log($scope.UserData);
for (var i = 0; i < $scope.UserData.length; i++) {
if ($scope.UserData[i].UserName == $scope.User.UserName && $scope.UserData[i].Password == $scope.User.Password) {
authService.currentuser = $scope.User.UserName;
//console.log(authService.currentuser);
$scope.loginstatus = 1;
break;
}
}
if ($scope.loginstatus == 1) {
// var lastVal = $cookieStore.get($scope.User.UserName);
// console.log(lastVal);
//$location.path('/app/playlists');
$scope.loginstatus = 0;
$state.go('app.playlists', null, {
reload: true
});
} else {
console.log('wrong credentials');
$scope.toast();
}
}).error(function(err) {
console.log(err);
});
}
});
So i want to enable automatic login, till the user clicks logout button. How it can be done?
I'm simply redirecting to another page when username and password matches.
You can check if the user is logged in in the module.run() method. Here is an example:
http://arthur.gonigberg.com/2013/06/29/angularjs-role-based-auth/
It might help you.
Please following below links.
How to check authentication and automatically redirect to login state with ui-router?
angular js returning user autologin

Managed authentication roles in spring boot and angularjs

I have a bit trouble finding out how i can managed my authentication roles on the front end. I want to access the authentication role and pass it to the root scope but it returns an array instead.
I want to know which role the user has add some privilege to each roles.
How could this be done ?
If i call user /user
{"details":{"remoteAddress":"0:0:0:0:0:0:0:1","sessionId":"1F64CC142A715A53FFF4A9329E6B933D"},"authorities":[{"authority":"USER_ROLE"}],"authenticated":true,"principal":{"password":null,"username":"1#1","authorities":[{"authority":"USER_ROLE"}],"accountNonExpired":true,"accountNonLocked":true,"credentialsNonExpired":true,"enabled":true},"credentials":null,"name":"1#1"}
This is my login controller :
(function () {
'use strict';
angular
.module('app')
.controller('LoginController', LoginController);
LoginController.$inject = ['$rootScope', '$scope', '$http', '$location', '$route','$localStorage'];
function LoginController($rootScope, $scope, $http, $location, $route,$localStorage) {
$scope.tab = function(route) {
return $route.current && route === $route.current.controller;
};
var authenticate = function(credentials, callback) {
var headers = credentials ? {
authorization : "Basic "
+ btoa(credentials.username + ":"
+ credentials.password)
} : {};
$http.get('user/', {
headers : headers
}).success(function(data) {
if (data.name) {
//This returns an array...
console.log(data.authorities);
console.log("Good Credentials");
$rootScope.authenticated = true;
} else {
$rootScope.authenticated = false;
}
callback && callback($rootScope.authenticated);
}).error(function() {
$rootScope.authenticated = false;
callback && callback(false);
});
};
authenticate();
$scope.credentials = {};
$scope.login = function() {
authenticate($scope.credentials, function(authenticated) {
if (authenticated) {
console.log("Login succeeded");
console.log($scope.credentials.username);
$location.path("/app/dashboard");
$scope.error = false;
$rootScope.authenticated = true;
//Here we add all the variables we need to the session that are safe to be seen
//In the future we can replace this and load this in the splash screen every time the application loads so we are sure the
// variables are stored
} else {
console.log("Login failed")
$location.path("/login");
$scope.error = true;
$rootScope.authenticated = false;
}
})
};
//Logout
$scope.logout = function() {
$http.post('logout', {}).success(function() {
$rootScope.authenticated = false;
$location.path("/");
}).error(function(data) {
$location.path("/");
console.log("Logout failed")
$rootScope.authenticated = false;
});
}
}
})();
This is my controller
#RequestMapping("/user")
public Principal user(#AuthenticationPrincipal Principal user) {
return user;
}
As described in the Spring documentation, #AuthenticationPrincipal will return value to the Authentication.getPrincipal(). However, if you look at Authentication, you will see that the authorities of the user are accessed separately from the principal, using Authentication.getAuthorities().
You can do a couple of things, either modify your custom Principal to also include the roles of the users, or you can also grab the authorities and serialize them in addition to the principal within your controller.
You can get the current authentication via: SecurityContextHolder.getContext().getAuthentication();

Angular jwt authentication fails when reloads the page

I'm trying to authenticate user through token. if i login then token will be created and stored in local storage. whenever there is a change in route I'm hitting the api which is built in express js , gives me decoded user value. everything works without refresshing page. Once I refresh the page I'm not able to hit the API. in order to get decoded user value i suppose to click on login button which is there in header , which triggers the route change then again everything works fine. Please help me out .
.controller('mainController', function($rootScope, $location, $window ,Auth){
var vm = this;
$rootScope.loggedIn = Auth.isLoggedIn();
$rootScope.$on('$locationChangeStart', function(){
$rootScope.loggedIn = Auth.isLoggedIn();
Auth.getUser()
.then(function(data){
$rootScope.user = data.data;
});
});
vm.login = function(){
......
}
vm.logout = function(){
......
}
})
Service
.factory('Auth', function($http, $q, AuthToken){
var authFactory = {};
authFactory.login = function(username, password){
return $http.post('/api/login', {
username: username,
password: password
})
.success(function(data){
AuthToken.setToken(data.token);
return data;
});
};
authFactory.logout = function(){
AuthToken.setToken();
};
authFactory.isLoggedIn = function(){
if(AuthToken.getToken()){
return true;
} else {
return false;
}
};
authFactory.getUser = function(){
if(AuthToken.getToken()){
return $http.get('/api/me');
} else {
return $q.reject({ message: "User has no token"});
}
};
return authFactory;
})
factory for setting token and interceptor code
.factory('AuthToken', function($window){
var authTokenFactory = {};
authTokenFactory.getToken = function(){
return $window.localStorage.getItem('token');
};
authTokenFactory.setToken = function(token){
if(token){
$window.localStorage.setItem('token', token);
} else {
$window.localStorage.removeItem('token');
}
};
return authTokenFactory;
})
.factory('AuthInterceptor', function($q, $location, AuthToken){
var interceptorFactory = {};
interceptorFactory.request = function(config){
var token = AuthToken.getToken();
if(token){
config.headers['x-access-token'] = token;
}
return config;
};
interceptorFactory.responseError = function(response){
if(response.status == 403){
$location.path('/login');
}
return $q.reject(response);
};
return interceptorFactory;
});
It may be that you have to reset the $http default headers on refresh. Using cookies in my case, I make a call to the following function at the beginning of $on('$stateChangeStart'):
service.RefreshGlobalVars = function () {
if ($http.defaults.headers.common.RefreshToken == null) {
$http.defaults.headers.common.Authorization = "Bearer " + $cookieStore.get('_Token');
$http.defaults.headers.common.RefreshToken = $cookieStore.get('_RefreshToken');
}
};
edit- to clarify, since I haven't seen your setToken() function, your implementation may vary, but that's pretty much the gist of it.
I got answer, solved it by checking route change in the main app.js, inside run block.
MyApp.run(function ($rootScope, $location, Auth){
$rootScope.loggedIn = Auth.isLoggedIn();
$rootScope.$on('$locationChangeStart', function(){
$rootScope.loggedIn = Auth.isLoggedIn();
Auth.getUser()
.then(function(data){
$rootScope.user = data.data;
});
});

First time injection doesn't instantiate

First time calling, the authenticated property is false, even the credential is OK. If I login once again with the same credential, it will be OK.
Anyway, I am not sure that my factory below is the right way in angularjs or not. Would you please give me any suggestions?
Factory:
app.factory('authenticatorService',['$resource', function($resource){
var authenticator = {};
authenticator.attempt = function(email, password){
var current = this;
$resource("/service/authentication/:id",null,{'update' : { method: 'PUT'}})
.save({'email' : email,'password': password},
//success
function(response){
current.authenticated = sessionStorage.authenticated = true;
current.userinfo = response.user;
current.authenticated = true;
},
function(response){
current.authenticated = false;
}
);
return this.authenticated;
};
authenticator.logout = function(){
delete sessionStorage.authenticated;
this.authenticated = false;
this.userinfo = null;
return true;
};
authenticator.check = function(){
if(this.userinfo && this.authenticated){
return true;
}
return false;
};
return authenticator;
}]);
Controller:
app.controller('authenCtrl',
[
'authenticatorService',
'$scope',
'$sanitize',
'$log',
'$location',
function(alert, authenticator, $scope, $sanitize, $log, $location){
$scope.login = function(){
if(authenticator.attempt($sanitize($scope.email) ,$sanitize($scope.password))){
$location.path('/dashboard');
}else{
alert.add("danger","Login fail.");
}
}
}]);
The this.authenticated in authenticator.attempt will return before the asynchronous call from $resource has completed.
You will need to wait for the promise to be resolved before returning from the factory, and before receiving in the controller.
Something like this should hopefully work:
Factory:
authenticator.attempt = function(email, password){
var current = this;
$resource("/service/authentication/:id", null, {'update' : { method: 'PUT'}})
.save({'email' : email,'password': password},
function(response){
current.authenticated = sessionStorage.authenticated = true;
current.userinfo = response.user;
current.authenticated = true;
},
function(response){
current.authenticated = false;
}
).$promise.then(function () {
return current.authenticated;
});
};
Controller:
$scope.login = function() {
var email = $sanitize($scope.email);
var password = $sanitize($scope.password);
authenticator.attempt(email, password).then(function(isAuthenticated) {
if (isAuthenticated) $location.path('/dashboard');
else alert.add("danger", "Login fail.");
});
};

Resources