Managed authentication roles in spring boot and angularjs - 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();

Related

Angularjs, value coming in token from backend not working in client side

What is wrong with the code it's not working, I am trying to request call web service from backend written in spring, the value passing from backend is token wrapped, I am trying to run the code on client side but form is not passing any value.
auth.js
'use strict';
angular. module('app')
.factory('Auth', [ '$http', '$rootScope', '$window', 'Session', 'AUTH_EVENTS',
function($http, $rootScope, $window, Session, AUTH_EVENTS) {
var authService = {};
this.isLoggedIn = function isLoggedIn(){
return session.getUser() !== null;
};
//the login function
authService.login = function(user, success, error) {
$http.post('URL: http://xxx.xxx.x.xx:xxxx/xxxx/authenticateUser').success(function(authData) {
//user is returned with his data from the db
var users = data.users;
if(users[user.username]){
var loginData = users[user.username];
//insert your custom login function here
if(user.username == loginData.username && user.password == loginData.username){
localStorageService.set(['userInfo'],
{ token: result.access_token, userName: loginData.userName });
//delete password no/t to be seen clientside
delete loginData.password;
//update current user into the Session service or $rootScope.currentUser
//whatever you prefer
Session.create(loginData);
//or
$rootScope.currentUser = loginData;
//fire event of successful login
$rootScope.$broadcast(AUTH_EVENTS.loginSuccess);
//run success function
success(loginData);
} else{
//OR ELSE
//unsuccessful login, fire login failed event for
//the according functions to run
$rootScope.$broadcast(AUTH_EVENTS.loginFailed);
error();
}
}
});
};
//check if the user is authenticated
authService.isAuthenticated = function() {
return !!Session.user;
};
//check if the user is authorized to access the next route
//this function can be also used on element level
//e.g. <p ng-if="isAuthorized(authorizedRoles)">show this only to admins</p>
authService.isAuthorized = function(authorizedRoles) {
if (!angular.isArray(authorizedRoles)) {
authorizedRoles = [authorizedRoles];
}
return (authService.isAuthenticated() &&
authorizedRoles.indexOf(Session.userRole) !== -1);
};
//log out the user and broadcast the logoutSuccess event
authService.logout = function(){
Session.destroy();
localStorageService.removeItem("userInfo");
$rootScope.$broadcast(AUTH_EVENTS.logoutSuccess);
}
return authService;
} ]);
authInterceptor
(function () {
'use strict';
var app = angular.module('app');
var factoryId = 'authInterceptor';
app.factory(factoryId, authInterceptor);
authInterceptor.$inject = ['$q', '$location', 'localStorageService', $rootScope, $http];
function authInterceptor($q, $location, localStorageService) {
var service = {
request: request,
responseError: responseError,
};
return service;
function request(config) {
config.headers = config.headers || {};
var authData = localStorageService.get('authorizationData');
if (authData) {
config.headers.Authorization = 'Bearer ' + authData.token;
}
return config;
}
function responseError(error) {
var loggedIn = false;
var authData = localStorageService.get('authorizationData');
if (authData) {
loggedIn = true;
}
//We only want to go to the login page if the user is not
//logged in. If the user is logged in and they get a 401 is
//because they don't have access to the resource requested.
if (error.status === 401 && !loggedIn) {
$location.path('/login').replace();
}
return $q.reject(error);
}
}
})();

Satellizer error

angular.module('starter')
.controller('LoginCtrl', function($scope, $location, $stateParams, $ionicHistory, $http, $state, $auth, $rootScope) {
$scope.loginForm = {}
$scope.loginError = false;
$scope.loginErrorText;
$scope.login = function() {
var credentials = {
email: $scope.loginForm.email,
password: $scope.loginForm.password
}
console.log(credentials);
$auth.login(credentials).then(function() {
console.log('im in login function' );
// Return an $http request for the authenticated user
$http.get('http://localhost:8000/api/v1/auth/user').success(function(response){
// Stringify the retured data
var user = JSON.stringify(response.user);
// Set the stringified user data into local storage
localStorage.setItem('user', user);
// Getting current user data from local storage
$rootScope.currentUser = response.user;
// $rootScope.currentUser = localStorage.setItem('user');;
$ionicHistory.nextViewOptions({
disableBack: true
});
$state.go('app.jokes');
})
.error(function(){
$scope.loginError = true;
$scope.loginErrorText = error.data.error;
console.log($scope.loginErrorText);
})
});
}
});
When i call the login function i get this error
POST http://localhost:8100/auth/login 404 (Not Found)
Is there problem with the satellizer?
I was also suffering from same issue. I just added
$authProvider.loginUrl = myServer+ 'oauth/token';
$authProvider.tokenName = 'access_token';
$authProvider.tokenPrefix = 'myServerAuth';
$authProvider.tokenHeader = 'Authorization';
$authProvider.tokenType = 'Bearer';
in my config and it worked fine.

AngularJs call a function only after a factory function is called

I am trying login user using factory function in angularjs.
This is my code for checking login info:
$scope.login = function(user) {
if(!$rootScope.isLoggedIn) {
LoginService.login($scope.user, $scope);
console.log($rootScope.isLoggedIn);
} else {
$location.path('/home');
}
}
While LoginService factory service look like this:
.factory('LoginService', ['$http', '$location', '$rootScope', function($http,$location, $rootScope) {
return {
login: function(user, scope) {
$rootScope.processGoingOn = true;
var $promise = $http.post('user.php', user);
$promise.then(function(msg) {
var responseData = msg.data;
console.log(responseData);
if(responseData['login_success'] == 'true') {
$rootScope.isLoggedIn = true;
$rootScope.processGoingOn = false;
// success redirect
} else {
$rootScope.isLoggedIn = false;
$rootScope.processGoingOn = false;
// try login again
}
});
}
....
}
});
The change in $rootScope.isLoggedIn is not reflecting back to $scope.login() function in either success or failure, any suggestions?
this is because login function is returned before promise is resolved.
on way to do this can be return $promise like this
login: function(user, scope){
$rootScope.processGoingOn = true;
return $http.post('user.php', user);
}
call then where you have console.log($rootScope.isLoggedIn);

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;
});
});

Prevent AngularJS Controller call if unauthenticated

I have a basic authentication check on route change which simply checks the existence of a SessionStorage key/val. However, I have noticed that if an unauthenticated user navigates to a forbidden page who's controller contains an AJAX call, the AJAX call still happens in the background even though the forbidden page doesn't load and the user is instead redirected to login. To get around this, I have added the same authentication check in every controller. This is becoming a bit tedious and I was wondering if there is a better way, or a way I can globally check authentication before a controller's methods are run. Here is the auth function on route change:
app.run(function ($rootScope, $location, authenticationService) {
$rootScope.clearAlerts = function(){
$rootScope.alerts = []
}
$rootScope.credentials = {
username: "",
password: ""
};
$rootScope.goto = function(url){
$location.path(url);
}
$rootScope.authenticated = authenticationService.isLoggedIn()
$rootScope.logOut = function () {
authenticationService.logOut();
}
var publicRoutes = ['/login'];
$rootScope.$on('$routeChangeStart', function (event, next, current) {
$rootScope.credentials.from = $rootScope.desiredPath || '/login'
$rootScope.authenticated = authenticationService.isLoggedIn();
if (!_(publicRoutes).contains($location.path()) && !$rootScope.authenticated) {
$rootScope.desiredPath = $location.path();
$location.path('/login');
}
})
})
I suggest you should check authentication on server side and return appropriate message on client side
Below is the url help
http://www.espeo.pl/2012/02/26/authentication-in-angularjs-application
and Write global handler in client side to check it
Below is a sample code:
angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives'], function ($routeProvider, $locationProvider, $httpProvider) {
var interceptor = ['$rootScope', '$q', function (scope, $q) {
function success(response) {
return response;
}
function error(response) {
var status = response.status;
if (status == 401) {
window.location = "./index.html";
return;
}
// otherwise
return $q.reject(response);
}
return function (promise) {
return promise.then(success, error);
}
}];
$httpProvider.responseInterceptors.push(interceptor);

Resources