Disable basic authentication for specific end point, and keep all other secured - spring-boot

Right now I configure web security adapter like -
#EnableWebSecurity
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()
.authorizeRequests()
.anyRequest()
.fullyAuthenticated().and()
.httpBasic().and()
.csrf()
.disable();
}
}
Which working fine and blocking all requests if not authenticated. But now I want to block all but /login. I mean, I want JUST /login and /login/* to be insecure, and rest of the app to be secured.
Anyone knows how can I achieve that?

Try to add the /login url to ignore list in WebSecurityConfigurerAdapter:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
#Override
public void configure(WebSecurity webSecurity) throws Exception{
webSecurity
.ignoring()
.antMatchers("/login");
}
}

Related

How to secure #PostMapping endpoint by spring security without secure #GetMapping

I would like to add Spring Security to my app on few endpoints.
#RestController
#RequestMapping("/test")
#RequiredArgsConstructor
public class TestController {
#PostMapping
public ResponseEntity post() {
...
}
#GetMapping
public ResponseEntity get() {
...
}
In web security conifure adapter I know how to secure endpoit. I did:
#Configuration
#EnableWebSecurity
#RequiredArgsConstructor
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
private final MyUserDetailsService myUserDetailsService;
#Override
public void configure(HttpSecurity http) throws Exception {
http.httpBasic().and()
.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/users", "/users/**").permitAll()
.anyRequest().authenticated()
;
}
In endpoint "/test" I would like to add security in #PostMapping where only authenticated users will be able to post something. #GetMapping will be open for everyone.
EDIT
So I updated my MyWebSecurityConfig:
#Override
public void configure(HttpSecurity http) throws Exception {
http.httpBasic().and()
.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/users", "/users/**").permitAll()
.antMatchers(HttpMethod.GET, "/shapes").permitAll()
.antMatchers(HttpMethod.GET, "/shapes/history").permitAll()
.anyRequest().authenticated()
;
}
but I can't still send Get on "/shapes" endpoit without authentication.
I am still getting 401 Unauthorized. What should I change?
There is an overrided version of antMatchers() that allow you to configure matching a HTTP method and the path together :
.authorizeRequests()
.antMatchers("/users", "/users/**").permitAll()
.antMatchers(HttpMethod.GET,"/test").permitAll()
.antMatchers(HttpMethod.POST, "/test").authenticated()

Cannot access to unsecured endpoints in Spring Boot

In my controller I have two endpoints where one is secured and one is public:
#GetMapping("/public")
public String getPublic() {
return "public";
}
#PreAuthorize("hasRole('USER')")
#GetMapping("/private")
public String getPrivate() {
return "public";
}
Secured endpoint works only when I am logged and token with right role is placed in request header. But when I want access to public endpoint without token I always got status 401 with error
Full authentication is required to access this resource
Here is my security configuration:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.csrf().disable();
}
}
and authorization server config:
#Configuration
#EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private final UserDetailsService appUserDetailService;
private final AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancer())
.authenticationManager(authenticationManager)
.userDetailsService(appUserDetailService);
}
}
I also tried change .authorizeRequests().anyRequest().authenticated() to this : .authorizeRequests().anyRequest().permitAll() with no change. My preferred way is handle security with annotations. Thank you.
You have two options, can go with either.
Option 1: In your endpoint, change like this.
#PreAuthorize("permitAll()")
#GetMapping("/public")
public String getPublic() {
return "public";
}
And change your configure(HttpSecurity http) method, do like this.
#Override
public void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.anyRequest().permitAll()
.and()
.csrf().disable();
}
Option 2: In your configure(HttpSecurity http) method, just do like this.
#Override
public void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/public").permitAll()
.anyRequest().authenticated()
.and()
.csrf().disable();
}
antMatchers() will do the trick. We use it a lot. It is also better to have insecured endpoints in different class and control security on class level through request mapping.
antMatchers("/public").permitAll()
Link to spring security api - https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/config/annotation/web/builders/HttpSecurity.html#antMatcher-java.lang.String-

Spring multiple authentication methods for different api endpoints

I want to check for different authentication methods for different endpoints. Methods i want to use are x509 and jwt. I need to use only x509 for certain endpoint and use JWT for all other requests.
Here's my web security configuration:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Configuration
#Order(1)
public static class ApiWebSecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/transaction/testf").authenticated().and()
.x509()
.subjectPrincipalRegex("CN=(.*?)(?:,|$)")
.userDetailsService(new X509UserDetailsService())
;
}
}
#Configuration
#Order(2)
public static class ApiTokenSecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/oauth/token", "/api/dealer/login").permitAll()
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
;
}
}
}
This configuration only checks /api/transaction/testf endpoint for x509 certificate and allows all other endpoints to respond. I need other endpoints to return 503 without a jwt token.
You have two filter chains. Neither of them have an entry point pattern properly configured http.antMatcher. That means they are configured to use /** as their entry point pattern.
For example
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().fullyAuthenticated()
is the same thing as saying:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**")
.authorizeRequests()
.anyRequest().fullyAuthenticated()
What we are saying here is
http - the security filter chain
http.antMatcher - the entry point to the security filter chain
http.authorizeRequests - start of my endpoint access restrictions
http.authorizeRequests.antMatchers - list of URLs with specific access
So what you need to do is change your #Order(1) filter chain to narrow down the pattern. For example: http.antMatcher("/api/transaction/**")
Your configuration will now look like
#Configuration
#Order(1)
public static class ApiWebSecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/transaction/**") //customized entry point
.authorizeRequests()
.antMatchers("/api/transaction/testf").authenticated().and()
.x509()
.subjectPrincipalRegex("CN=(.*?)(?:,|$)")
.userDetailsService(new X509UserDetailsService())
;
}
}
#Configuration
#Order(2)
public static class ApiTokenSecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**") //this is default
.authorizeRequests()
.antMatchers("/oauth/token", "/api/dealer/login").permitAll()
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
;
}
With your existing configuration the filter chain named ApiWebSecurityConfig will trap all calls. The other filter chain, ApiTokenSecurityConfig, is never used.
Since WebSecurityConfigurerAdapter is #Deprecated, preferable use multiple SecurityFilterChain (see updated Multiple HttpSecurity):
#Bean
#Order(1)
public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**")
.authorizeHttpRequests(authorize -> authorize
.anyRequest().hasRole("ADMIN")
)
.httpBasic(withDefaults());
return http.build();
}
#Bean
public SecurityFilterChain formLoginFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.formLogin(withDefaults());
return http.build();
}

Spring oauth2 : Access any resource server endpoint without Authentication

I have a scenario where I want to allow user to access a particular endpoint at resource server(running at 8098) from client application (running at 8080) without authentication. When ever I am trying to access it without client authentication it gives error access is denied. But when I access the same endpoint after user logged-in it working.
I have following configuration at resource server:
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Autowired
private CustomUserDetailsService userDetailsService;
public ResourceServerConfiguration() {
super();
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.anonymous()
.and()
.authorizeRequests()
.antMatchers("/api/requestdetails/view-all-details/**").permitAll()
.anyRequest().authenticated()
}
}
basically I want to make this endpoint "/api/requestdetails/view-all-details/** unsecured. so user can access it without authentication.
I did some changes in config method and now it's working.
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Autowired
private CustomUserDetailsService userDetailsService;
public ResourceServerConfiguration() {
super();
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**")
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/api/requestdetails/view-all-details/**").permitAll()
.antMatchers("/api/**").authenticated()
}
}

Spring boot: Securing api endpoint with oauth2 while having mvc UI pages

I'm trying to get a spring-boot mvc application working with standard login while exposing some API endpoints with oAuth2 security.
Basically my requirements are as follows:
If a user hits the home page ("/") check if it's authenticated.
If not show the login form, else show the home page.
But a user should also be able to ask for an oauth authentication token and with that token acces /api/assignment/{id}.
I can get the standard login to work, and I can get the oauth2 to work but I can not get them to work together.
This is my configuration at the moment:
WebSecurityConfig
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(this.dataSource).passwordEncoder(new BCryptPasswordEncoder());
}
}
OAuth2Config
#Configuration
#EnableResourceServer
#EnableAuthorizationServer
public class OAuth2Config {
protected static final String RESOURCE_ID = "oauthdemo";
#Configuration
#EnableResourceServer
protected static class ResourceServer extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.authorizeRequests()
.antMatchers("/js/**", "/css/**", "/images/**", "/webjars/**", "/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(RESOURCE_ID);
}
}
#Configuration
#EnableAuthorizationServer
protected static class AuthServer extends AuthorizationServerConfigurerAdapter {
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.allowFormAuthenticationForClients();
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client")
.authorizedGrantTypes("password", "refresh_token")
.authorities("ROLE_USER")
.scopes("read")
.resourceIds(RESOURCE_ID)
.secret("secret").accessTokenValiditySeconds(3600);
}
}
}
The problem is I always get the following error when trying to open the home page ("/")
<oauth>
<error_description>
Full authentication is required to access this resource
</error_description>
<error>unauthorized</error>
</oauth>
It does not redirect to the login page.
I do not need this page to be protected by oauth2, but even if i go directly to the login page ("/login", which i can access) and supply credentials I still get the 'full authentication is required' error.
Even though i disabled basic http authentication.
Does anyone know how to separate the normal user UI from the api endpoints that need to be protected by OAuth2?
Can you try this
http
.authorizeRequests()
.antMatchers("/js/**", "/css/**", "/images/**", "/webjars/**", "/login").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/home").authenticated();
Considering /home is a page that needs to be authorized.
Hi you have to specify filters used for each config in your case you need:
in web security configurtion
http
.authorizeRequests()
.antMatchers("/api/**","/oauth/**")
.permitAll()
.and()
.......
this will let web security bypass authorization/resource servers URLs
and in resource server security configuration
http
.antMatcher("/api/**")
.authorizeRequests()
.anyRequest()
.authenticated();
this will let resource security bypass all URLs except "/api/**".
in this way you can ignore orders of configuration there is another option by make one of above actions and put its configuration in early order using #Order

Resources