spring securty SimpleUrlAuthenticationFailureHandler - spring

#Component
public class TrackerAuthFailureHandler extends SimpleUrlAuthenticationFailureHandler{
#Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
if(exception.getClass().isAssignableFrom(DisabledException.class)){
super.setDefaultFailureUrl("/accountRecovery");
}
super.onAuthenticationFailure(request, response, exception);
}
}
SpringSecurity.java
#Autowired
private TrackerAuthFailureHandler trackerAuthFailureHandler;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.failureHandler(trackerAuthFailureHandler);
}
Is there anything wrong with my code. After authentication failure, Page is not redirect to "/accountRecovery" url.

Related

Spring Security - ant matcher permit all not working

I have a problem with antMatchers. This is not working as I expected.
I try to permit for All endpoint /tokens/**, but when this endpoint is called, my filters are called too(JwtTokenVerifier)
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/tokens/**").permitAll()
.anyRequest().authenticated()
.and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.cors()
.and()
.addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), this.jwtProperties, objectMapper))
.addFilterAfter(new JwtTokenVerifier(this.jwtProperties), JwtUsernameAndPasswordAuthenticationFilter.class);
}
Every time when I try to access for example /tokens/refresh-access-token JwtTokenVerifier is called.
#PostMapping("/tokens/refresh-access-token")
#ResponseStatus(HttpStatus.OK)
public Map<String,String> refreshAccessToken(#RequestBody String refreshToken)
Token verifier:
public class JwtTokenVerifier extends OncePerRequestFilter {
private final JwtProperties jwtProperties;
public JwtTokenVerifier(JwtProperties jwtProperties) {
this.jwtProperties = jwtProperties;
}
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
If possible, you could try and exclude the URL completely from Spring Security processing, by overriding the WebSecurity method. I don't know, though, if you want to completely ignore the FilterChain for that path.
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/tokens/**");
}

Spring security AuthenticationServiceException converted to InsufficientAuthenticationException

I've a problem with exception handling during authentication using Spring Security.
This is my AuthenticationProvider where on every exception an AuthenticationServiceException is thrown.
#Component
public class MyAuthenticationProvider implements AuthenticationProvider {
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
try {
// ...
} catch (Exception e) {
throw new AuthenticationServiceException(e.getMessage(), e);
}
}
}
Below my custom AuthenticationProvider.
#Component
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
log.debug(e.toString());
}
}
This is the security config
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AuthenticationProvider authenticationProvider;
#Autowired
private AuthenticationEntryPoint authenticationEntryPoint;
#Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(authenticationProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint);
}
}
Everything is triggered as expected. The problem is that in the AuthenticationProvider the AuthenticationException is an instance of InsufficientAuthenticationException and not AuthenticationServiceException as thrown by the AuthenticationProvider.
What I want instead in MyAuthenticationEntryPoint is the exception thrown with the cause set, which is a custom exception.
How can I solve this?
Why Spring replace an AuthenticationServiceException with an InsufficientAuthenticationException?
Thanks in advance.
SOLUTION
I found the solution! The problem is in SecurityConfig class. .authenticationEntryPoint(authenticationEntryPoint) must be under .httpBasic() and not set globally.
The right configuration is the following:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.csrf().disable();
}

Spring security only allowed oauth login

In my project, i just want to allow oauth login. my spring security config as follow:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/login.html", "/oauth/**", "/sign**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().disable()
.httpBasic().disable()[enter image description here][1]
.exceptionHandling().accessDeniedPage("/login.html")
.and()
.apply(new SpringSocialConfigurer());
}
The problem is the access denied page not working. I want to get login.html content as follow:
login.html
in fact i got 403 page as follow:
403
How to solve this problem?
I solve this problem, the code as follow:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login.html", "/oauth/**", "/sign**").permitAll()
.anyRequest()
.authenticated()
.and()
.exceptionHandling()
.defaultAuthenticationEntryPointFor(new HttpForbiddenEntryPoint(), AnyRequestMatcher.INSTANCE)
.and()
.logout()
.logoutUrl("/logout.html")
.clearAuthentication(true)
.logoutSuccessUrl("/login.html")
.and()
.apply(new SpringSocialConfigurer());
}
The entry point:
public class HttpForbiddenEntryPoint implements AuthenticationEntryPoint {
private String redirect_url = "/login.html";
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.sendRedirect(redirect_url);
}
public String getRedirect_url() {
return redirect_url;
}
public void setRedirect_url(String redirect_url) {
this.redirect_url = redirect_url;
}
}

How to disable the 'Authentification required popup' in Spring server configuration?

The route /gateways needs authentication.
When /gateways is accessed in the browser I am redirected to /login and the following form appears:
If /gateways is accessed from an angular2 app the following popup appears:
My spring security configuration is the following:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static String REALM="Authentication";
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("cris").password("123").roles("ADMIN");
auth.inMemoryAuthentication().withUser("felix").password("felix123").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.formLogin()
.and()
.authorizeRequests()
.antMatchers("/user", "/vehicles", "/signin", "/isautheticated").permitAll().anyRequest()
.authenticated();
}
// Access-Control-Allow-Origin header to be present
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}
/* To allow Pre-flight [OPTIONS] request from browser */
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
}
So how can the popup be disabled?
You should specify formLogin() instead of httpBasic() in your configuration. your configure method should look like this.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage("/login");
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.formLogin()
.and()
.authorizeRequests()
.antMatchers("/user", "/vehicles", "/signin", "/isautheticated").permitAll().anyRequest()
.authenticated();
}
I think your request from angular2 is taking an invalid Authorization Basic header, it was handled by BasicAuthenticationFilter, and it threw a AuthenticationException, and start to entry point.
You can implement your own entry point that implements AuthenticationEntryPoint, and then inject to BasicFilter, the default entry point is BasicAuthenticationEntryPoint. As you can see, it will return a WWW-Authenticate response header.
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.addHeader("WWW-Authenticate", "Basic realm=\"" + realmName + "\"");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
authException.getMessage());
}

Spring LogoutSuccessHandler not invoked

I'm using spring-boot (1.3.5) + oauth2 (spring-cloud-starter-oauth2). I would like to test some LogoutSuccessHandler but I'm unable to invoke it.
This is my security configuration:
#Configuration
#EnableWebSecurity
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private LogoutHandler logoutHandler;
#Override
public void configure(HttpSecurity http) throws Exception {
http
.anonymous().disable()
.httpBasic().disable()
.authorizeRequests()
.antMatchers("/index.html", "/", "/resources/**", "/css/**").permitAll()
.anyRequest().authenticated();
http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessHandler(logoutHandler);
//.invalidateHttpSession(true).deleteCookies("JSESSIONID", "SESSION");
}
}
This is my logoutHandler
#Component
public class LogoutHandler extends AbstractAuthenticationTargetUrlRequestHandler implements LogoutSuccessHandler {
#Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
setDefaultTargetUrl("/");
super.handle(request, response, authentication);
}
}
When I debug the application and put the breakpoint to the logoutHandler it's never invoked. Am I missing something in this configuration?
Thanks
Update your configure method a little bit. You don't have to use AntPathRequestMatcher to match logout url.
#Override
public void configure(HttpSecurity http) throws Exception {
http
.anonymous().disable()
.httpBasic().disable()
.authorizeRequests()
.antMatchers("/index.html", "/", "/resources/**", "/css/**").permitAll()
.anyRequest().authenticated()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(logoutHandler)
//.deleteCookies("JSESSIONID", "JSESSIONID")
//.invalidateHttpSession(true)
.permitAll();
}

Resources