I would like to give access to /hello URL to users which has a role 'ADMIN'
I have a security configuration like this. From "/authenticate" URL I am getting the jwt token.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authenticate").permitAll()
//.antMatchers("/hello").hasRole("ADMIN")
.anyRequest().authenticated().
and().
exceptionHandling().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
I have tried to add #PreAuthorize annotation in my Controller, but it's not working all users have an access to that url.
#GetMapping("/hello")
#PreAuthorize("hasRole('ADMIN')")
public String test(){
return "Hello";
}
After removing #PreAuthorize annotation from the controller and changing the security configuration like this it solved my problem.
#Darren Thanks a lot for your comment it resolved my issue.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authenticate").permitAll()
.antMatchers("/hello").hasAuthority("ADMIN")
.anyRequest().authenticated().
and().
exceptionHandling().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter,
UsernamePasswordAuthenticationFilter.class);
}
Related
I need to add a basic auth in only one of my controller method
Other method don't have an auth, but still have a #PreAuthorize in order to check if the parameters are valid.
My issue is , httpbasic transform all the exception throwed by preAuthorize in 401 ( some should be 403, etc).
I have the feeling that all my endpoint are under a basic auth, not just the ones I have use #Secured
How can I avoid that?
My code:
#Controller
class MyController {
#Secured("BASIC_AUTHENTIFIED")
public void someMethodOnlyForAuthentified(){...}
#PreAuthorize("check(parameters)")
public void someMethodForEveryone(List<String> parameters){...}
}
And in my security config:
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser(login).password(password).roles("BASIC_AUTHENTIFIED");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.authorizeRequests().antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and().httpBasic()
.and().csrf().disable();
}
I have used following code to restrict put, delete and options request in my web app but the test response shows 200 OK.
Any suggestion?
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.and().formLogin().loginPage("/login").permitAll()
.and().logout().logoutSuccessHandler(customLogOutHandler()).permitAll();
http.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").denyAll()
.antMatchers(HttpMethod.PUT, "/**").denyAll()
.antMatchers(HttpMethod.DELETE, "/**").denyAll();
super.configure(http);
http.cors();
}
Remove super.configure(http); which will override your configuration with below and denyAll() will not deny the request with methods
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().and()
.httpBasic();
}
Try to configure Spring Security so that access to particular URL patterns are secured differently depending on the HTTP method used to access the URL pattern.
http.authorizeRequests().antMatchers(HttpMethod.OPTIONS,"/path/to/deny").denyAll();
http.authorizeRequests().antMatchers(HttpMethod.DELETE,"/you/can/alsoSpecifyAPath").denyAll();
http.authorizeRequests().antMatchers(HttpMethod.PUT,"/and/can/haveWildcards/*").denyAll();
I configure WebSecurityConfig, create user in memory
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("username")
.password(passwordEncoder().encode("password"))
.authorities("READ_ORDERS")
.roles("USER");
}
configure WebSecurityConfig
#Configuration
#Order(1)
public static class BasicAuthenticationAdapter extends WebSecurityConfigurerAdapter {
private final AuthenticationEntryPoint authEntryPoint;
#Autowired
public BasicAuthenticationAdapter(AuthenticationEntryPoint authEntryPoint) {
this.authEntryPoint = authEntryPoint;
}
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/orders**")
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.csrf().disable()
.httpBasic().authenticationEntryPoint(authEntryPoint)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
When i try to Authorise with invalid credentials first time - 401 exception, it's ok.
But after successful authorization, when i use invalid username and password,
i also authorised.
What can be the problem ?
That is how basic authentication works. As soon as you have logged in successfully the valid credentials will always be posted.
Spring security works with SessionCreationPolicy, and default policy is IF_REQUIRED. It means spring creates session if it does not have and is required.
In order to solve your issue you have to change this policy.
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
Restart your server and try again.
I have the following security adapter for my Spring REST service to use HTTP basic http auth.
Right now, when I try to send a request to any GET HTTP endpoint, the request is successfully authorized and processed. But all other HTTP methods are returning 401. Any idea?
#EnableWebSecurity
public class WebSecurityAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password(passwordEncoder().encode("password")).roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").hasRole("USER").and().httpBasic();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
You have an AuthenticationException which is a runtime exception. Read about it here Spring Security Authentication.
The default configuration of WebSecurity, as said here HttpSecurity is:
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
Try to add .anyRequest().authenticated() to your code.
I have a problem regarding on the controllers request from a spring boot application.
I have made a certificate in order to run the app on https. The certificate works fine, it is valid.
My main problem is when i test my methods from the controller through postman they(the url reques) work fine on https and http...it shouldn't work on http. Can someone help on this ?
This is my WebSecurityConfig class:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
public static final String AUTHENTICATED_HEADER_NAME = "Authenticated";
public static final String AUTHENTICATED_TRUE = "true";
public static final String AUTHENTICATED_FALSE = "false";
#Autowired
public void globalUserDetails(final AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
auth.userDetailsService(authenticationManager).passwordEncoder(passwordEncoder);
}
#Override
#Bean(value = "authenticationManagerBean")
public org.springframework.security.authentication.AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Configuration
#Order(1)
public static class HTTPBasicSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
//todo check how we can change the root url of swagger
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/documentation**", "/configuration/**", "/v2/api-docs**", "/swagger-ui.html", "/webjars/**", "/swagger-resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
//todo http basic allows access to all urls after login
http
.httpBasic()
.and()
.csrf().disable()
.antMatcher("/api/**")
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest()
.authenticated();
}
}
#Configuration
#Order(2)
public static class FormLoginSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
//todo more investigation is required to check if it is safe to ignore csrf for login
.ignoringAntMatchers("/login")
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.permitAll()
.successHandler((httpServletRequest, httpServletResponse, authentication) -> {
httpServletResponse.setHeader(AUTHENTICATED_HEADER_NAME, AUTHENTICATED_TRUE);
})
.failureHandler((httpServletRequest, httpServletResponse, e) -> {
httpServletResponse.setHeader(AUTHENTICATED_HEADER_NAME, AUTHENTICATED_FALSE);
httpServletResponse.setStatus(SC_UNAUTHORIZED);
})
.and()
.logout().permitAll()
.and()
.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class)
.addFilterBefore(new CsrfHeaderFilter(), CsrfFilter.class);
http.exceptionHandling().authenticationEntryPoint((HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) -> {
if (authException != null) {
response.setStatus(SC_UNAUTHORIZED);
}
});
}
}
#Configuration
#Order(3)
public static class TestClass extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.headers()
.httpStrictTransportSecurity()
.includeSubDomains(true)
.maxAgeInSeconds(31536000);
}
}
}
and this is my spring boot version
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
<relativePath></relativePath>
</parent>
Your question is touching on several points:
you can require clients to require secure channels, by adding the security.require_ssl=true configuration property (see the Spring Boot reference documentation about HTTPS)
or use the following configuration snippet http.requiresChannel().anyRequest().requiresSecure();
you might want to enforce that as well with HSTS in Spring Security
None of the above helped the situation I was in.
I figured out that chrome (postman) was automatically transforming my http requests to https.
On the other browsers http requests didn't worked.