As the title says Spring security's ant matcher's permit all doesn't work at all here's the method for it
#Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers( "/css/*", "/js/*", "index").permitAll()
.antMatchers(HttpMethod.POST, "/api/v1/user/auth/register").permitAll()
.antMatchers("/get", "/delete/*", "/api/v1/user/auth/**").hasRole(ADMIN.name())
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
it should only allow the url ending with /get to be accessed by user that has admin role but I can access it without it (USER role) is there anything I'm doing wrong?
I tried changing the endpoint but didn't succeed at all
Related
I'm trying to use Spring Security in my project, here is the code:
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// TODO Auto-generated method stub
//super.configure(auth);
//auth.inMemoryAuthentication().withUser("admin").password("1111").roles("USER");
auth
.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select username, password, 1 from users where username=?")
.authoritiesByUsernameQuery("select users_username, roles_id from roles_users where users_username=?")
.rolePrefix("ROLE_");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable();
http
.httpBasic();
http
.authorizeRequests()
.anyRequest().authenticated();
http
.authorizeRequests()
.antMatchers("/users/all").hasRole("admin")
.and()
.formLogin();
http
.exceptionHandling().accessDeniedPage("/403");
}
Here is the problem:
Imagine we have two users (one with the user role and the other one with the admin role) in our database one admin and the second is a user, the problem is when I connect as user (which has only user role) it can access to admin resources (and this is not the expected behavior).
I think the problem in this query:
"select username, password, 1 from users where username=?"
According that username is the primary key?
If anyone has an idea how I can resolve this problem?
Your first matcher anyRequest() is always applied, because the order of matchers is important, see HttpSecurity#authorizeRequests:
Note that the matchers are considered in order. Therefore, the following is invalid because the first matcher matches every request and will never get to the second mapping:
http.authorizeRequests().antMatchers("/**").hasRole("USER").antMatchers("/admin/**")
.hasRole("ADMIN")
Your modified and simplified configuration:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/users/all").hasRole("admin")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.exceptionHandling().accessDeniedPage("/403");
}
The problem is with the ordering of your rules when you configure your HttpSecurity. What's happening is when the request comes in and hits the
authorizeRequests().anyRequest().authenticated()
and since the user is authenticated it never makes it to the
.antMatchers("/users/all").hasRole("admin")
Here is an example of how you can configure it:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/public").permitAll()
.antMatchers("/user").hasRole("USER")
.antMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.exceptionHandling().accessDeniedPage("/403");
}
It uses the chain of responsibility pattern. It will go through the chain of rules until it finds a rule that matches. Any rules that come after the rule that matches are never reached. Generally when writing the rules for authenticated requests, the more specific rule will come first.
I'm developing a spring-boot application and its spring security configuration is as follows:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.antMatchers("/actuator/**", "/login*", "/logout*")
.permitAll();
httpSecurity
.cors().and()
.csrf().disable()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/taas/v1/**").hasRole("admin")
.antMatchers("/taas/v1/teams", "/taas/v1/profiles", "/taas/v1/tests/summary").hasRole("tester")
.antMatchers( "/taas/v1/teams", "/taas/v1/tests/summary").hasRole("user")
.anyRequest().authenticated()
.and()
.exceptionHandling().accessDeniedHandler(customAccessDeniedHandler)
.and()
.httpBasic()
.and()
.formLogin()
.successHandler(customAuthenticationSuccessHandler)
.failureHandler(customAuthenticationFailureHandler)
.and()
.logout()
.logoutSuccessHandler(customLogoutSuccessHandler())
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID");
}
}
Even though i have set the url pattern for each roles. All users are able to access all endpoints as mentioned in antMatchers(). A user with role user is not supposed to access /taas/v1/profiles. But when I try to access that endpoint by logging in as user, I'm getting the response but expected response is 403 forbidden.
I request someone to provide a workaround for me.
I got this issue resolved by doing some minor changes in my antMatchers(). Below is the modified code.
The main issue is that antMatcher() pattern must not contain the context path, see Spring security antMatcher does not work
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.cors()
.and()
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/profiles").hasAnyRole("TESTER")
.antMatchers( "/teams", "/tests/summary").hasAnyRole("USER", "TESTER", "ADMIN")
.anyRequest().authenticated()
.and().csrf().disable()
.exceptionHandling()
.accessDeniedHandler(customAccessDeniedHandler)
.and()
.httpBasic()
.and()
.formLogin()
.successHandler(customAuthenticationSuccessHandler)
.failureHandler(customAuthenticationFailureHandler)
.and()
.sessionManagement()
.invalidSessionUrl("/invalidSession.html")
.maximumSessions(1).sessionRegistry(sessionRegistry()).and()
.sessionFixation().none()
.and()
.logout()
.logoutSuccessHandler(customLogoutSuccessHandler())
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID");
}
}
Please verify the code that you're sharing because as you've mentioned. A user with role user is not supposed to access /ptaas/v1/profiles. But when I try to access that endpoint by logging in as user.
Where your mapping says you've not configured access to user role as given.
.antMatchers( "/taas/v1/teams", "/taas/v1/tests/summary").hasRole("user")
As per your comments it should have been .antMatchers( "/taas/v1/teams", "/taas/v1/tests/summary", "/ptaas/v1/profiles").hasRole("user")
Need to customise the default oauth2 authentication server /login page to user defined page along with passing query parameters
I tried by using this link https://www.javainuse.com/spring/boot_form_security_custom_login
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.antMatchers("/login","/oauth/authorize")
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.permitAll();
}
I want to secure my HATEOAS REST API build with Spring. All requests should need authorization and POST requests to "/rooms" should need the admin role. My WebSecurityConfigurerAdapter implementation code looks like this right now:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
// Todo: Make sure that all resources need to be authenticated and POST rooms needs ADMIN role
.anyRequest().authenticated()
.antMatchers(HttpMethod.POST, "/api/v1/rooms").hasRole("ADMIN")
.and()
.httpBasic()
.and()
.csrf().disable();
}
Right now all resources only need authentication if I put the "anyRequest().authenticated()" line before the "antMatchers..." line, but then the needed "ADMIN" role doesn't work or get applied and vice versa.
How am I to get both things working at the same time?
Kind Regards,
Florian
Securityconfiguration.java
#Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and().authorizeRequests().antMatchers("/public/**")
.permitAll().antMatchers("/sa/**").hasAuthority("sa")
.antMatchers("/admin/**").hasAuthority("admin")
.and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/index.html").and()
.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class)
.csrf().disable();
}
And in the rest controller use..
#RequestMapping("/admin/adduser")
public void addUser(#RequestBody User user) {
authService.addUser(user);
}
The following code did it for me:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/v1/rooms").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.csrf().disable();
}
}
Thank you for the response Pankaj.
I have swagger UI working with spring-boot. I have a stateless authentication setup for my spring rest api which is restricted based on roles for every api path.
However, I am not sure how can i put <server_url>/swagger-ui.html behind Basic authentication.
UPDATE
I have following websecurity configured via WebSecurityConfig
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/sysadmin/**").hasRole("SYSADMIN")
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/siteadmin/**").hasRole("SITEADMIN")
.antMatchers("/api/**").hasRole("USER")
.anyRequest().permitAll();
// Custom JWT based security filter
httpSecurity
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
}
One suggestion without knowing more about your configuration is from this SO question.
https://stackoverflow.com/a/24920752/1499549
With your updated question details here is an example of what you can add:
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/sysadmin/**").hasRole("SYSADMIN")
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/siteadmin/**").hasRole("SITEADMIN")
.antMatchers("/api/**").hasRole("USER")
// add the specific swagger page to the security
.antMatchers("/swagger-ui.html").hasRole("USER")
.anyRequest().permitAll();
// Custom JWT based security filter
httpSecurity
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
}
The problem with this is it only protects the Swagger UI page and not the API specification which is loaded as a .json file from that UI page.
A better approach is to put the swagger files under a path so that you can just add antMatchers("/swagger/**").hasRole("USER")
A bit late to answer. I carried out a small POC to execute the same. I am using Keycloak and Spring Security. Below is my configuration
http
.antMatcher("/**").authorizeRequests()
.antMatchers("/swagger-resources/**","/swagger-ui.html**","/swagger-ui/").hasRole("admin")
.anyRequest().authenticated()
.and()
.exceptionHandling()
.accessDeniedHandler(new AccessDeniedHandlerImpl())
.defaultAuthenticationEntryPointFor(authenticationEntryPoint(), new CustomRequestMatcher(AUTH_LIST))
.and()
.httpBasic()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.csrf().disable()
.logout()
.logoutUrl("/logout")
.invalidateHttpSession(true)
.clearAuthentication(true)
.addLogoutHandler(keycloakLogoutHandler());
I have a working example here