Reason for #EnableWebSecurity in the configuration class - spring

I just read answer from the another question What is the use of #EnableWebSecurity in Spring?, but i couldn't understand why we need to add #EnableWebSecurity annotation at all.
Even I remove the #EnableWebSecurity from the configuration, my application still works.
Let's assume that we are going to implement either JWT based (rest api) or simply login based mvc application. For the following configuration what i am missing?
#Component
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Bean
public UserDetailsService userDetailsService() {
return new MyCustomUserDetailsService();
}
#Bean
public PasswsordEncoder passwsordEncoder() {
return new BrcyptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// for the jwt authentication add jwt filter etc ..
// for the login based, override default login page, error page etc..
}
}

If you are not using spring-boot but just a pure spring project , you definitely need to add #EnableWebSecurity in order to enable spring-security.
But if you are using spring-boot 2.0 +, you do not need to add it by yourself because the spring-boot auto configuration will automatically do it for you if you forget to do so. Under the cover , it is done by the WebSecurityEnablerConfiguration which its javadoc also states this behaviour as follows:
If there is a bean of type WebSecurityConfigurerAdapter, this adds the
#EnableWebSecurity annotation. This will
make sure that the annotation is present with default security
auto-configuration and also if the user adds custom security and
forgets to add the annotation.

Related

How does spring security pass credentials? / Postman

I just created a basic layer to secure my Spring API.
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
#Override
public UserDetailsService userDetailsService() {
List<UserDetails> users = new ArrayList<>();
users.add(User.withDefaultPasswordEncoder().username("Admin").password("xxx!!").roles("ADMIN").build());
users.add(User.withDefaultPasswordEncoder().username("Pharmacist").password("xxx!!").roles("PHARMACIST").build());
users.add(User.withDefaultPasswordEncoder().username("Office").password("xxx!!").roles("OFFICE").build());
return new InMemoryUserDetailsManager(users);
}
}
I am using Postman to test my endpoints and it's working via the Authorization function of Postman.
What if I want to use this parameters (username,password,role) in my frontend?
I mean, that I am trying somehow to see how spring security passes the values to the url: http://localhost:8080 but i cant find out how. I need this to be able to handle in my Frontend with these vaules.
I am really new in this Spring Security Chapter.

#EnableOAuth2Sso AND #EnableResourceServer in same app

I'd like have a set of services that can be used with "Client Credential" (for machine to machine) and with OAuth2 Single Sign On for the regular webapp (which is served by the same application).
I tried setting both #EnableOAuth2Sso and #EnableResourceServer; I expected to have the app "try" the token based and then fall back to SSO redirect in case it doesn't find any and the user does not have a session.
Each config works fine on its own (with a:
#Bean
public RemoteTokenServices ...
for #EnableResourceServer to configure the "CheckTokenEndpointUrl").
But as soon as I try with both I get:
APPLICATION FAILED TO START
Description:
Method springSecurityFilterChain in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a single bean, but 2 were found:
- userInfoTokenServices: defined by method 'userInfoTokenServices' in class path resource [org/springframework/boot/autoconfigure/security/oauth2/resource/ResourceServerTokenServicesConfiguration$RemoteTokenServicesConfiguration$UserInfoTokenServicesConfiguration.class]
- remoteTokenServices: defined by method 'remoteTokenServices' in class path resource [my/CustomWebSecurityConfigurerAdapter.class]
In your spring boot application class use the #EnableOAuth2Sso annotation and in the configuration class use #EnableResourceServer annotation and in this class define the endpoints to be used with access tokens.
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/user") //end point that needs access token in header
.antMatcher("/info") //end point that needs access token in header
.authorizeRequests().anyRequest().authenticated();
}
}
For more information refer the link

How to designate public endpoints using custom annotation in spring rest controllers?

We are using OAuth2 for securing our REST endpoints. Nearly all of our endpoints require authentication. We have couple of public endpoints. We configure spring security using #EnableWebSecurity. All the public endpoints are explicitly listed in the configuration (see "publicpath_x" in the example below). Instead of explicitly adding each new public enpodint in the configuration, it would be much easier to have a custom annotation, e.g. #PublicAccess which will designate each public endpoint. Is it possible to configure that endpoints annotated with this annotation will be considered as public, i.e. no authentication will be required? We don't want to designate public endpoints in path (e.g. all public endpoints path will start/end with "/public").
Security configuration:
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//...
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatchers("publicpath1", "publicpath2").permitAll() //...
}
}
Example public REST controller with custom annotation:
#RestController
public class PublicController1 {
#PublicAccess //our custom annotation
#RequestMapping(value = "publicpath1", method = RequestMethod.GET)
public void publicEndpoint1() {
//...
}
}
I was trying the following classes with no success.
javax.servlet.Filter
org.springframework.web.servlet.handler.HandlerInterceptorAdapter
You can use the #PreAuthorize Annotations as method security
Detail see here

Spring Boot with Custom Converters breaks Swagger & how to move it

I have a very simple Spring Boot application. I launch this through the basic SpringApplication.run(Startup.class, args); and have a custom #Configuration class in there that overrides the default converters. I decided to add Swagger to the mix of things so that I can generate better documentation for our internal user base as there are gads of endpoints.
When I started things up, Swagger simply wouldn't work.
I decided to start a front-scratch Spring Boot with just one endpoint to document to see what went wrong. Out-of-the box this worked perfectly fine and I was able to get Swagger running via just hitting the http://localhost:8080/swagger-ui.html base URL.
When I implemented my custom #Configuration class that extended WebMvcConfigurationSupport, Swagger no longer worked.
My configuration overrode a single method:
#Configuration
public class StartupConfiguration extends WebMvcConfigurationSupport {
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(getJsonConverter());
}
}
That's it. I decided to add the default converters as well without any luck. Then I just emptied the class and left it as:
#Configuration
public class StartupConfiguration extends WebMvcConfigurationSupport {
}
Swagger is still broken - if I remove the class completely, then it works.
What can I do to keep my custom configuration data and run Swagger? I would also love to move it to something like http://localhost:8080/swagger/ rather than the default file it uses, but that is a completely separate issue for now.
My launch of Swagger looks like this:
#Configuration
#EnableSwagger2
public class SwaggerConfiguration {
#Bean
public Docket getDocket() {
// ...
return new Docket(DocumentationType.SWAGGER_2)
.groupName("Core API")
.apiInfo(infoBuilder.build())
.select().paths(PathSelectors.regex("/*"))
.build();
}
}
Overriding the default resource handler worked for me. I added the following to the configuration class extending WebMvcConfigurationSupport:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry
.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}

Spring OAuth Filter Chain & Java Config

I'm trying to add in spring-security-oauth to an existing app with spring-security. I'm using Java config.
I have an existing amended filter chain in place (with some custom filters added in) but requests to '/oauth/token' aren't using it, but are using the 'default' filter chain. How can i get access to the filter chain that's securing the oauth endpoints so that i can use the custom filters there also or can I wire in the OAuth endpoint(s) into the existing setup?
there is indeed a slightly smoother way using the interface AuthorizationServerConfigurer.
You can stick to the annotation #EnableAuthorizationServer and implement above interface in your configuration file. This will enable you to alter the oauth2-filter-chain by doing something like this:
#Configuration
#EnableWebSecurity
#EnableAuthorizationServer
public class SecurityConfig extends WebSecurityConfigurerAdapter
implements AuthorizationServerConfigurer
// some configuration ...
public void configure(AuthorizationServerSecurityConfigurer oauthSecurity) throws Exception {
oauthSecurity.addTokenEndpointAuthenticationFilter(new YourFilter());
}
// more configuration ...
}
In contrast to the addFilterXYX-methods of HttpSecurity you have no fine-grained influence here where the filter will be positioned in the filter chain. Any filter added by addTokenEndpointAuthenticationFilter will be inserted before the BasicAuthenticationFilter.
If you need to control the position of you filter in a more detailed way you could create a bean extending AuthorizationServerConfigurerAdapter instead of using the annotation #EnableAuthorizationServer. I did not try that but I guess you could then extend AuthorizationServerSecurityConfigurationlike systemfreund suggested without having to specify #Order(-1) because only your custom configuration gets imported. Probably you would also have to #Import AuthorizationServerEndpointsConfigurationlike it is done in the convenience annotation #EnableAuthorizationServer.
It's probably not the best way to do it, but I did not manage to find a better approach. The idea is to provide a custom AuthorizationServerSecurityConfiguration instance and override the default instance which is #Imported via #EnableAuthorizationServer. We just need to make sure to add an #Order annotation with higher precendence than the default configuration:
#EnableAuthorizationServer
#Import(CustomSecurityConfig.class)
public class Application {
}
#Configuration
#Order(-1)
public class CustomSecurityConfig extends AuthorizationServerSecurityConfiguration {
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http); // do the default configuration first
http
.addFilterBefore(new MyFilter(), ...);
}
}

Resources