Spring Boot 2.3.2 default security - spring-boot

I am using Spring Security for basic authentication. But it comes with default authentication.I am trying to disable it, disabling it through application.properties. This is what I tried:
SpringBasicSecurityApplication.java
#SpringBootApplication(exclude={SecurityAutoConfiguration.class})
#EnableWebSecurity
public class SpringBasicSecurityApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBasicSecurityApplication.class, args);
}
}
ApplicationController.java
#RestController
#RequestMapping("/rest/auth")
public class ApplicationController {
#GetMapping("/getMsg")
public String greeting() {
return "Spring Security Example!!!";
}
}
application.properties
spring.security.user.name=xusername
spring.security.user.passward=xpassword
server.port = 8081
logging.level.org.springframework.boot.autoconfigure.security=INFO
what am i doing wrong? thanks in advance.

Just give everyone permission to any request in config:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
// HTTP security configuration
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.anyRequest().permitAll
.and().httpBasic();
}
}

Thanks #Seldo97 you suggestion work for me but I want to give authentication for some special kind of URL so with help of your code I did like:-
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
auth.inMemoryAuthentication().withUser("user").password("user").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().antMatchers("/resto/**").hasRole("ADMIN").anyRequest().fullyAuthenticated().and()
.httpBasic();
`#Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}`
Thank you for your help :)

Related

How to configure oAuth2 when Authorization Server is also the Resource server

I'm trying to setup a very basic oAuth2 authentication in spring boot 2.x.x using either authorization code grant or implicit grant but I can't seem to access the Resource server (which resides in the same spring boot app as the Authorization server) after the token is obtained.
Following is the configuration of WebSecurityConfigurerAdapter
#EnableWebSecurity
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final String[] IGNORE_URIS = {
"/swagger-resources/**",
"/swagger-ui.html",
"/v2/api-docs",
"/webjars/**",
"/resources/**",
"/h2-console/**",
"/common/**",
"/configuration/ui",
"/configuration/security",
"/error"
};
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers(IGNORE_URIS);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/product/**")
.hasAnyRole("ADMIN").and()
.httpBasic().and().formLogin().and().authorizeRequests().anyRequest().authenticated();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("{noop}admin").roles("ADMIN");
}
#Bean
public PasswordEncoder bCrypt() {
return new BCryptPasswordEncoder();
}
And the AuthorizationServerConfigurerAdapter
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private final AuthenticationManager authenticationManager;
#Autowired
public AuthorizationServerConfiguration(AuthenticationConfiguration authenticationConfiguration) throws Exception {
this.authenticationManager = authenticationConfiguration.getAuthenticationManager();
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("my-client-id")
.authorizedGrantTypes("authorization_code", "implicit")
.authorities("ADMIN")
.scopes("all")
.resourceIds("product_api")
.secret("{noop}secret").redirectUris("https://google.com").accessTokenValiditySeconds(0);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()")
.checkTokenAccess("permitAll()");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
So far so good. I am able to reach the default Spring login page by typing the following Url in the browser.
http://localhost:8080/oauth/authorize?response_type=token&client_id=my-client-id&redirect_uri=https://google.com
Then The login page shows up and I enter my credentials.
After I log in I can then grant access to "my-client-id" app.
Eventually after I approve the app I can see the newly generated access token in the URL bar of the browser which is something like this.
https://www.google.com/#access_token=f2153498-6a26-42c6-93f0-80825ef03b16&token_type=bearer&scope=all
My question is that All of this flow won't work when I also configure a Resource Server.
#EnableResourceServer
#Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId("product_api");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers("/**")
.and().authorizeRequests()
.antMatchers("/**").permitAll();
}
}
What am I doing wrong? When I try to access the oauth/authorize url as before I get the following:
Why? How can one access the login page and retrieve the token? What Am I missing?
You need to use
#Order
Annotation to specify order for WebMvc and ResourceServer classes
#EnableWebSecurity
#Configuration
#Order(1)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
...
}
and for Resource Server
#EnableResourceServer
#Configuration
#Order(2)
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
...
}
If you want to see workable example, you can check it here https://github.com/alex-petrov81/stackoverflow-answers/tree/master/auth-server-also-resource
I've created it from your code example.

spring security | security config permitall not working

#EnableWebSecurity
public class WebSecurityConfig implements WebMvcConfigurer {
#Bean
public UserDetailsService userDetailsService() throws Exception {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withDefaultPasswordEncoder().username("user").password("user").roles("USER").build());
return manager;
}
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers("/css/**").permitAll()
.anyRequest().authenticated();
}
}
Above code is not working, url: localhost:8080/css/styles.css is redirecting to login page.
The code layout is, src/main/resources/static folder has html, css and js folders inside of which files remain.
Thanks in advance.
I think addResourceHandlers method can help you.
public class WebSecurityConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");
}
}
it means find your resources in your static folder.
Not sure if this will work, but currently in my project, this is my config. and it's working properly.
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(HttpMethod.GET, "/js/**", "/css/*", "/images/**")
.permitAll()
.anyRequest()
.authenticated();
}

Multiple user details services for different endpoints

I am building a REST API using Spring and am currently authenticating all my requests using a custom user details service and this configuration code:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
}
I am also setting up a DaoAuthenticationProvider to use the my user details service and using that to configure global security.
Now, I want to provide an endpoint that (while still secured with HTTP basic authentication) uses a different user details service to check whether the user is allowed to access the given resource.
How do I use two different user details services for different endpoints?
One thing you can do is have two WebSecurityConfigurerAdapters:
#EnableWebSecurity
#Order(Ordered.HIGHEST_PRECEDENCE)
class FirstEndpointConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) {
http
.requestMatchers()
.antMatchers("/specialendpoint")
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.userDetailsService(/* first of your userDetailsServices */);
}
}
#Configuration
class SecondEndpointConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) {
http // all other requests handled here
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.userDetailsService(/* second of your userDetailsServices */);
}
}
requestMatchers() exists for targeting springSecurityFilterChains to specific endpoints.
EDIT: Mahmoud Odeh makes a good point that if the user bases are the same, then you may not need multiple UserDetailsService instances. Instead, you can use one change that isolates your special endpoint by an authority on the user's account:
http
.authorizeRequests()
.antMatchers("/specialendpoint").hasAuthority("SPECIAL")
.anyRequest().authenticated()
.and()
.httpBasic();
Then, your single UserDetailsService would look up all users. It would include the SPECIAL GrantedAuthority in the UserDetails instance for users who have access to /specialendpoint.
I am trying to follow the solution given by M. Deinum but in my case it always goes to the same user service (v2userDetailsService) regardless of which URL is executed /v3/authorize/login or /v2/authorize/login. Here is my code:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration {
#Configuration
#Order(2)
public static class V2Configuration extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("v2userDetailsService")
private UserDetailsService v2userDetailsService;
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
ShaPasswordEncoder passwordEncoder = new ShaPasswordEncoder(256);
auth
.userDetailsService(v2userDetailsService)
.passwordEncoder(passwordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and().csrf().disable().headers()
.frameOptions().disable().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/app").permitAll()
.antMatchers("/v2/authorize/login").permitAll()
.antMatchers("/v2/authorize/reLogin").permitAll()
.antMatchers("/v2/authorize/logout").permitAll();
}
}
#Configuration
#Order(1)
public static class V3Configuration extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("v3UserDetailsService")
private UserDetailsService v3UserDetailsService;
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
ShaPasswordEncoder passwordEncoder = new ShaPasswordEncoder(256);
auth
.userDetailsService(v3UserDetailsService)
.passwordEncoder(passwordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and().csrf().disable().headers()
.frameOptions().disable().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/v3/authorize/login").permitAll()
.antMatchers("/v3/authorize/reLogin").permitAll()
.antMatchers("/v3/authorize/logout").permitAll();
}
}
}

Spring boot and spring security multiple login pages

#EnableWebSecurity
public class MultiHttpSecurityConfig {
#Configuration
#Order(1)
public static class App1ConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/my/**", "/account/**").access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
.and().formLogin().loginPage("/login");
}
}
#Configuration
#Order(2)
public static class App2ConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
.and().formLogin().loginPage("/adminlogin");
}
}
}
This is supposed be two different login forms. My problem is that the one with the highest order /adminlogin is not displayed. I have idea why? Please help. The code is from Spring boot - how to configure multiple login pages?
Following Sofia's suggestion I tried this:
#Configuration
#Order(2)
public static class UserConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatcher(new AntPathRequestMatcher("/my/**"))
.csrf().disable()
.authorizeRequests().antMatchers("/my/**").access("hasRole('ROLE_USER')")
.and().formLogin().loginPage("/login");
}
}
#Configuration
#Order(1)
public static class AdminConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatcher(new AntPathRequestMatcher("/admin/**"))
.csrf().disable()
.authorizeRequests().antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
.and().formLogin().loginPage("/adminlogin");
}
}
But in both cases /login is called
I reckon that the reason why your admin login is not activating is because: first, it is NOT higher in priority.
#Order defines the sort order for an annotated component.
The value is optional and represents an order value as defined in the Ordered interface. Lower values have higher priority. The default value is Ordered.LOWEST_PRECEDENCE, indicating lowest priority (losing to any other specified order value).
Second, according to HttpSecurity's Javadoc:
A HttpSecurity is similar to Spring Security's XML element in the namespace configuration. It allows configuring web based security for specific http requests. By default it will be applied to all requests, but can be restricted using requestMatcher(RequestMatcher) or other similar methods.
So try restricting the HttpSecurity object to activate for your admin pages by first configuring the requestMatcher such that:
http
.requestMatcher(new AntPathRequestMatcher("/admin/**"))
.csrf().disable()
.authorizeRequests().antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
.and().formLogin().loginPage("/adminlogin");
I solved it using request matcher:
#Configuration
#EnableWebSecurity
public class AllConfig extends WebSecurityConfigurerAdapter {
#Autowired
MyUserDeatailService myuserDetailsService;
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider());
}
#Bean
public static BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(4);
}
#Bean
public AuthenticationProvider authProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(myuserDetailsService);
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
#Bean
public static AuthenticationFailureHandler customAuthenticationFailureHandler() {
return new CustomAuthenticationFailureHandler();
}
#Configuration
#Order(1)
public static class AdminSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(new AntPathRequestMatcher("/admin/**"))
.csrf().disable()
.authorizeRequests()
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
.and().formLogin()
.loginPage("/admin/adminlogin").permitAll().usernameParameter("username")
.passwordParameter("password").defaultSuccessUrl("/admin/AdminDashBoard")
.failureHandler(customAuthenticationFailureHandler()).and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/home").and()
.exceptionHandling().accessDeniedPage("/403");
}
}
#Configuration
#Order(2)
public static class UserSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(new AntPathRequestMatcher("/user/**"))
.csrf().disable()
.authorizeRequests()
.antMatchers("/user/**").access("hasRole('ROLE_USER')").and().formLogin()
.loginPage("/user/userlogin").permitAll().usernameParameter("username")
.passwordParameter("password").defaultSuccessUrl("/user/UserDashBoard")
.failureHandler(customAuthenticationFailureHandler()).and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/").and()
.exceptionHandling().accessDeniedPage("/403");
}
}
}

Spring Security PreAuthorize Custom Method Bean resolver is not registered?

Im just learning Spring, going through tutorials and testing possibilities. One of my goals is to secure a Service Method using a Custom Method and the PreAuthorize annotation. Unfortunaly the Bean holding the custom Method cannot be resolved and I dont know why. Maybe someone can see the error at first sight.
Bean holding the custom Method:
#Component("mySecurityService")
public class MySecurityService {
public boolean hasPermission() {
return true; //simple implementation just to look if has permission is called
}
}
Service to be Secured:
public interface OrderService {
#PreAuthorize("#mySecurityService.hasPermission()")
public AllOrdersEvent requestAllOrders(RequestAllOrdersEvent requestAllCurrentOrdersEvent);
public OrderDetailsEvent requestOrderDetails(RequestOrderDetailsEvent requestOrderDetailsEvent);
public OrderStatusEvent requestOrderStatus(RequestOrderStatusEvent requestOrderStatusEvent);
public OrderCreatedEvent createOrder(CreateOrderEvent event);
public OrderUpdatedEvent setOrderPayment(SetOrderPaymentEvent setOrderPaymentEvent);
public OrderDeletedEvent deleteOrder(DeleteOrderEvent deleteOrderEvent);
}
Java Security Config:
#EnableWebSecurity
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("letsnosh").password("noshing").roles("USER");
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean(name = "mySecurityService")
MySecurityService createSecurityService(){return new MySecurityService();}
#Override
protected void configure(HttpSecurity http) throws Exception {
/*
http.authorizeUrls()
.antMatchers("/aggregators*//**//**").hasRole("USER")
.anyRequest().anonymous()
.and()
.httpBasic();
*/
}
}
Error:
No bean resolver registered in the context to resolve access to bean 'mySecurityService'
Hello I solved the problem. It was connected to the Version of Spring Security.
I got the Version from the official Spring Rest Tutotrial : 3.2.0.M2
In this version I had to declare the Security Context as follows:
#EnableWebSecurity
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("letsnosh").password("noshing").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeUrls()
.antMatchers("/aggregators/**").hasRole("USER")
.anyRequest().anonymous()
.and()
.httpBasic();
}
}
Here the error was thrown.
But using a newer Version of Spring Security: 3.2.5.RELEASE
I could declare the Config this way:
#EnableWebSecurity
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeUrls()
.antMatchers("/aggregators*//**//**").hasRole("USER")
.anyRequest().anonymous()
.and()
.httpBasic();
}
And the bean could be resolved, using either #Component Annotaions directly on the MySecurityService class or #Bean annotations on a config class method which returns a MySecurityService instance.

Resources