Authorization of access to resources with spring security and Angularjs - java

I made permission to access resources in spring security as shown in this code: "The user authentication is then from the DB"
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
protected void globalConfig(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
//auth.inMemoryAuthentication().withUser("user").password("123").roles("USER");
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select username as principal, password as credentials, etat as actived from utilisateurs where username=?")
.authoritiesByUsernameQuery("select u.username as principal, ur.nom_role as role from utilisateurs u inner join roles ur on(u.roles_id=ur.id_role) where u.username=?")
.rolePrefix("ROLE_");
}
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement().maximumSessions(100).maxSessionsPreventsLogin(false).expiredUrl("/Login");
http
.authorizeRequests()
.antMatchers("/AppJS/**","/images/**","/pdf/**","/Template/**","/Views/**","/MainApp.js").permitAll()
.antMatchers("/Users/**").access("hasRole('ADMIN')")
.antMatchers("/Dashbord/**").access("hasRole('ADMIN')")
.antMatchers("/Login*").anonymous()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/Login").permitAll()
.defaultSuccessUrl("/home")
.failureUrl("/Login?error=true")
.and().exceptionHandling().accessDeniedPage("/Access_Denied")
.and()
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutUrl("/logout")
.permitAll()
.logoutSuccessUrl("/Login");
}
}
Subsequently, I specified the views for each URL:
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter{
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/Login").setViewName("Login");
registry.addViewController("/Dashbord").setViewName("home");
registry.addViewController("/logout").setViewName("Login");
registry.addViewController("/Users").setViewName("Views/ListUsers");
}
}
I used the angularJS routeProvider to keep track of URLs:
var app = angular.module('Mainapp', ['ngRoute','file-model','ui.bootstrap','ngMessages']);
app.config(function($routeProvider) {
$routeProvider
.when('/Users', {
controller:'UsersController',
templateUrl: 'Views/ListUsers'
})
.when('/Dashbord', {
controller: 'ResultController',
templateUrl: 'Views/home.html'
});
});
My problem is how to make the link of the access authorization that I
defined in spring security with the URLs of angularjs ($
routeProvider)
Thank you,
and Have a good day,

You could try enable html5mode, to get this
AngularJS: http://localhost:8080/Users
app.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/Users', {
controller:'UsersController',
templateUrl: 'Views/ListUsers'
})
.when('/Dashbord', {
controller: 'ResultController',
templateUrl: 'Views/home.html'
});
$locationProvider.html5Mode(true)
});

I am not sure this will meets your requirement but yes i have already did before with the use of ngPermission. Before that you need list of the roles to set in your route.
.state('view1', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl',
resolve: {
authorization: ["ngPermissionService", function (ngPermissionService) {
//you need to call webserivce at this level for get all user's permissions and return it.
return ngPermissionService.role(["admin"])
}]
}
});
For more details click here

Related

Spring security don't show images befor loging in. How to fix?

I can't see the image on my site before logging in. How can I solve this problem?
Below is the class of my spring security config. I think problem is inside this class.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home" , "/about", "/blog/**", "/blog", "/blog/add", "/registration").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/sign-in")
.permitAll()
.and()
.logout()
.permitAll();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.passwordEncoder(NoOpPasswordEncoder.getInstance())
.usersByUsernameQuery("select username, password, active from usr where username=?")
.authoritiesByUsernameQuery("select u.username, ur.roles from usr u inner join user_role ur on u.id = ur.user_id where u.username=?");
}
}
try adding this method to WebSecurityConfig
e.g for images located in static resource directory at: src/main/resources/static/images
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/images/**");
}
As i understood you have a problem to pass the static resources from spring security filter. for this problem you need to change your configuration to exclude the address of your static resources which in your case it is picture. in resources folder on your project create the new folder called image and than add your picture into it and add these lines of code in your spring security config
.antMatchers("/","/public/**", "/resources/**","/resources/image/**")
.permitAll()

Postman showing HTML instead of JSON

I have a simple Spring Boot + Spring Security REST app with quotations. Only 3 endpoints for GET, POST, DELETE. Only moderator and admin accounts defined. GET rest method works fine - it shows list of quotations. The problem is with POST and DELETE methods. When I try to invoke them in Postman it returns HTML (logging form defined in SecurityConfig).
QuotationApi.java
#RestController
public class QuotationApi {
private List<Quotation> quotations;
public QuotationApi() {
this.quotations = new ArrayList<>();
quotations.add(new Quotation("Those who dare to fail miserably can achieve greatly.", "John F. Kennedy"));
quotations.add(new Quotation("Get busy living or get busy dying.", "Stephen King"));
}
#GetMapping("/api")
public List<Quotation> getQuotation() {
return quotations;
}
#PostMapping("/api")
public boolean addQuotation(#RequestBody Quotation quotation) {
return quotations.add(quotation);
}
#DeleteMapping("/api")
public void deleteQuotation(#RequestParam int index) {
quotations.remove(index);
}
}
SecurityConfig.java
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// creating users
#Bean
public UserDetailsService userDetailsService() {
UserDetails moderator = User.withDefaultPasswordEncoder()
.username("user")
.password("user")
.roles("MODERATOR")
.build();
UserDetails admin = User.withDefaultPasswordEncoder()
.username("admin")
.password("admin")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(moderator, admin);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(HttpMethod.GET,"/api").permitAll()
.antMatchers(HttpMethod.POST,"/api").hasRole("MODERATOR")
.antMatchers(HttpMethod.DELETE,"/api").hasRole("ADMIN")
.anyRequest().hasRole("ADMIN")
.and()
.formLogin().permitAll()
.and()
.logout().permitAll()
.and()
.csrf().disable();
}
}
I have Basic_auth in Postman:
EDIT after Andreas's help (working code):
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(HttpMethod.GET,"/api").permitAll()
.antMatchers(HttpMethod.POST,"/api").hasRole("MODERATOR")
.antMatchers(HttpMethod.DELETE,"/api").hasRole("ADMIN")
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic()
.and()
.formLogin().permitAll()
.and()
.logout().permitAll()
.and()
.csrf().disable();
}
Doesn't matter that Postman is sending Basic authentication header, when you haven't enabled Basic authentication in Spring.
Since you only called formLogin() to enable form based authentication, you have to login using the form POST.
Of course, you could just call httpBasic() to enable Basic authentication too.

spring security login 404

im exploring a little of spring.
i got across spring boot for easy endpoints see:
#Controller
#EnableAutoConfiguration
public class SampleController {
#RequestMapping("/sample")
#ResponseBody
String sample() {
return "Hello sample!";
}
#RequestMapping("/sample2")
#ResponseBody
String sample2() {
return "Hello sample secured!";
}
}
logically the endpoints are accessible on localhost:8181/sample
but on using spring security the "protected" endpoint becames unaccessible because the login page gives me 404
my security class is as follows:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/sample" ).permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Bean
#Override
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
i am able to access /sample as is not protected. but unable to access /sample2 as it redirects to /login
im configuring my security class according to this guide: https://spring.io/guides/gs/securing-web/
I am able to access /sample as is not protected. But unable to access
/sample2 as it redirects to /login
Because you have not by-passed /sample2 in your security configuration.
.antMatchers("/sample2" ).permitAll()
Another thing is that as you have specified custom login page
.formLogin()
.loginPage("/login")
you have to provide a login page.
Inject userDetailsService into authenticationProvider:
#Bean
public AuthenticationProvider authenticationProvider(){
DaoAuthenticationProvider authenticationProvider=new CustomAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService());
return authenticationProvider;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.authenticationProvider(authenticationProvider());
}
Add this configuration to spring security:
.antMatchers("/sample2").hasRole("USER")

Spring form login, multiple roles with form issue

Ok so I have my login page on localhost/login there I have two forms with the same action which is /login (for now). I am trying to accomplish this scenario:
User is on the login page, he is offered a choice between two forms 1. offers a form which will redirect him to /employees/home 2. offers form for /administrator/home. Keep in mind that user that has ADMIN role can log to the /employees/home as well
The application has two roles ADMIN and EMP.
I want the web app to be able to grant authority correctly for each user and redirect him where it is needed. I am able to do this with a single role but as soon as i put in another one, the app starts to lose it. This is my code:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
private DataSource dataSource;
#Value("${spring.queries.users-query}")
private String usersQuery;
#Value("${spring.queries.roles-query}")
private String rolesQuery;
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.
jdbcAuthentication()
.usersByUsernameQuery(usersQuery)
.authoritiesByUsernameQuery(rolesQuery)
.dataSource(dataSource)
.passwordEncoder(bCryptPasswordEncoder);
}
protected void configure(HttpSecurity http) throws Exception {
http.
authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/admin/**").hasAuthority("ADMIN").anyRequest()
.authenticated().and().formLogin()
.loginPage("/login/administrator").failureUrl("/login?error=true")
.defaultSuccessUrl("/admin/home")
.usernameParameter("email")
.passwordParameter("password")
.and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/").and().exceptionHandling()
.accessDeniedPage("/access-denied")
.and()
.authorizeRequests()
.antMatchers("/employee/**").hasAuthority("EMP")
.anyRequest().authenticated().and().formLogin()
.loginPage("/login").failureUrl("/login?error=true")
.defaultSuccessUrl("/employee/home")
.usernameParameter("email")
.passwordParameter("password")
.and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/").and().exceptionHandling()
.accessDeniedPage("/access-denied")
;
/* http.
authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/admin/**").hasAuthority("ADMIN").anyRequest()
.authenticated().and().csrf().disable().formLogin()
.loginPage("/login").failureUrl("/login?error=true")
.defaultSuccessUrl("/admin/home")
.usernameParameter("email")
.passwordParameter("password")
.and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/").and().exceptionHandling()
.accessDeniedPage("/access-denied");*/
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**");
}
Queries
spring.queries.users-query=select email, password, active from user where email=?
spring.queries.roles-query=select u.email, r.role from user u inner join user_role ur on(u.user_id=ur.user_id) inner join role r on(ur.role_id=r.role_id) where u.email=?
Main login controller
#Controller
public class LoginController {
#RequestMapping(value={"/","/login"}, method = RequestMethod.GET)
public ModelAndView login(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("login");
return modelAndView;
}
Repositories and services work, they are tested with a single role. I figure that it is the issue with SecurityConfiguration class. NOTE*I have tried making several configuration classes with different orders, that did not work as well.
Any help would be much appreciated!! Thanks!
After some digging around managed to resolve the issue as Sankar stated with custom success handler class.
public class CustomSuccessHandler
implements AuthenticationSuccessHandler {
....
protected String determineTargetUrl(Authentication authentication) {
boolean isEmp= false;
boolean isAdmin = false;
Collection<? extends GrantedAuthority> authorities
= authentication.getAuthorities();
for (GrantedAuthority grantedAuthority : authorities) {
if (grantedAuthority.getAuthority().equals("EMPLOYEE")) {
isUser = true;
break;
} else if (grantedAuthority.getAuthority().equals("ADMIN")) {
isAdmin = true;
break;
}
}
if (isEmp) {
return "/employee/home";
} else if (isAdmin) {
return "/admin/home";
} else {
throw new IllegalStateException();
}
}
....
}
But at the end, decided to scrap the logic and switch to a single log in form which leads to landing page from where the user can choose where to go.
protected void configure(HttpSecurity http) throws Exception {
http.
authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/rest/**").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/landing").hasAnyAuthority("ADMIN","EMPLOYEE")
.antMatchers("/admin/**").hasAuthority("ADMIN")
.antMatchers("/employee/**").hasAuthority("EMPLOYEE")
.anyRequest()
.authenticated().and()
.formLogin()
.loginPage("/login").failureUrl("/login?error=true")
.defaultSuccessUrl("/landing")
.usernameParameter("email")
.passwordParameter("password")
.and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login").and().exceptionHandling()
.accessDeniedPage("/access-denied");
}
based on the user's role links to the /employee/home or /admin/home are disabled, or not.

Spring security WebSecurityConfigurerAdapter configuration issue

In the following class that extends WebSecurityConfigurerAdapter i've overwritten the configure(HttpSecurity) method.
#Configuration
#EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
public void configureAuth(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("fabio")
.password("123")
.roles("ADMIN")
.and()
.withUser("joe")
.password("123")
.roles("GUEST");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/post/list").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.logout();
}
}
With this i should be able to get to localhost:8080/post/list page without having to commit to a user login since it has the .permitAll() , but when i try to getting into it it always prompts the login page before, only after i enter the previous credentials i'm able to view it. How can i fix this ?
controller class
#RestController
#RequestMapping("/post")
public class HomeController {
#Secured("ROLE_GUEST")
#RequestMapping("/list")
public String list(){
return "list...";
}
#Secured("ROLE_USER")
#RequestMapping("/drafts")
public String drafts(){
return "drafts...";
}
#Secured({"ROLE_ADMIN","ROLE_USER"})
#RequestMapping("/add")
public String add(){
return "adding...";
}
}
According to the #RequestMapping definition there is a conflict because it is secured by annotation #Secured("ROLE_GUEST") but also you need to access it with .permitAll() configuration.
Option 1: Just remove the #Secured("ROLE_GUEST") in order to let .permitAll() do the work.
Option 2: use #Secured("ROLE_ANONYMOUS") on the #RequestMapping("/list") instead of #Secured("ROLE_GUEST"). You can see the definition of ROLE_ANONYMOUS in the Spring Documentation
It will depends on the path value after /post/list. Please see the following examples of how to define antMatchers depending on the path value.
localhost:8080/post/list = .antMatchers( "/post/list").permitAll()
localhost:8080/post/list/stuff = .antMatchers( "/post/list/**").permitAll()
localhost:8080/post/list, localhost:8080/post/list1234
= .antMatchers( "/post/list**").permitAll()
For more information visit the AnthPathMatcher documentation and HttpSecurity

Categories