AuthenticationException thrown in AuthenticationProvider is mapped to AccessDeniedException in ExceptionTranslationFilter - spring

Having written a custom AuthenticationProvider (which calls a service, after which that one calls an external URL to authenticate the given credentials), I wanted to customize the error message people get when their authentication fails, based on the message I pass to the instance of AuthenticationException (so the e.getMessage() passed to BadCredentialsExceptoin in the code below).
#Component
public class TapasAuthenticationProvider implements AuthenticationProvider {
#Override
public TapasAuthentication authenticate(Authentication authentication) throws AuthenticationException {
String userName = authentication.getName();
String password = authentication.getCredentials().toString();
try {
AuthenticationResponse authResponse = authenticationService.authenticate(userName, password);
return new TapasAuthentication(mapToAuthenticatedUser(authResponse, userName, password), password);
} catch (AuthenticationFailedException e) {
// Note that AuthenticationFailedException is a self-written exception, thrown by the authenticationService.
log.error("Authentication failed: ", e);
throw new BadCredentialsException(e.getMessage());
}
}
}
Now I looked up how to map AuthenticationExceptions and found that an AuthenticationEntryPoint should be used for this. So I created one and added it to my SecuritySetup:
#Component
public class TapasAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException {
System.out.println(authException.getMessage());
// More code to be added once exception is what I expect.
}
}
#Autowired
private TapasAuthenticationEntryPoint authenticationEntryPoint;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
.and()
.authorizeRequests().anyRequest().authenticated().and().httpBasic()
.and()
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
.and()
.csrf().disable();
}
This successfully triggers the AuthenticationEntryPoint, but instead of a BadCredentialsException, I get an InsufficientAuthenticationException. I checked the origin of this exception and it comes from the ExceptionTranslationFilter's handleSpringSecurityException. Here the exception turns out to be an AccessDeniedException instead of an AuthenticationException.
private void handleSpringSecurityException(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, RuntimeException exception)
throws IOException, ServletException {
if (exception instanceof AuthenticationException) {
// I would except to enter this if-statement, but exception is not what I expect
sendStartAuthentication(request, response, chain,
(AuthenticationException) exception);
}
else if (exception instanceof AccessDeniedException) {
....
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authenticationTrustResolver.isAnonymous(authentication) || authenticationTrustResolver.isRememberMe(authentication)) {
// Instead code comes here, and creates an InsufficientAuthenticationException.
sendStartAuthentication(
request,
response,
chain,
new InsufficientAuthenticationException(
messages.getMessage(
"ExceptionTranslationFilter.insufficientAuthentication",
"Full authentication is required to access this resource")));
}
...
}
}
Why does the exception not match my exception thrown in the AuthenticationProvider? And how would I be able to pass data from the AuthenticationProvider back to the user?

Turns out the HttpBasicConfigurer returned by the .basicSecurity() call also allows to register an AuthenticationEntryPoint. When registering it that way, the exception thrown by the Provider does end up in the entry point.
Security config looks like this:
#Autowired
private TapasAuthenticationEntryPoint authenticationEntryPoint;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic().authenticationEntryPoint(authenticationEntryPoint)
.and()
.csrf().disable();
}

Related

How to apply a security filter only on a restricted http path [duplicate]

This question already has answers here:
Disabling a filter for only a few paths in spring security
(2 answers)
Closed 1 year ago.
I have a problem with my Spring security configuration. I just want to basically apply an authentication filter to some paths, and not to other path. But the filter i have defined is applied on all the HTTP request ever what i write in the configuration.
Here is my code.
SecurityConfig:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private JwtFilter jwtFilter;
#Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password("{bcrypt}$2a$10$DmzAlIznZz3faNQx1eBTBOw6fNiGE105fKoHkvskYTMXH5OFUE6iy")
.roles("USER");
}
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.csrf().disable()
.antMatcher("/admin/**")
.authorizeRequests() //
.anyRequest().authenticated() //
.and()
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
#Override
#Bean(name = BeanIds.AUTHENTICATION_MANAGER)
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
JWTFilter:
#Component
public class JwtFilter extends OncePerRequestFilter {
#Autowired
private JWTUtils jwtUtils;
#Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException, ServletException, IOException {
String authorizationHeader = httpServletRequest.getHeader("Authorization");
String token = null;
String userName = null;
if (authorizationHeader != null) {
userName = jwtUtils.extractUsername(token);
}
if (jwtUtils.validateToken(token)) {
} else {
httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
if (userName != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
new UsernamePasswordAuthenticationToken(userName, null);
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}
For example if i try to call this servlet:
#PostMapping("/login")
public ResponseEntity<UserDetails> login(#RequestBody User user) throws Exception {
try {
Authentication authenticate = authenticate(user.getName(), user.getPassword());
UserDetails authenticatedUser = (UserDetails) authenticate.getPrincipal();
return ResponseEntity.ok()
.header(
HttpHeaders.AUTHORIZATION,
generateToken(authenticatedUser.getUsername())
)
.body(authenticatedUser);
} catch (BadCredentialsException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}
My filter is called to verify if the client is authenticated but it is my login end point so my client is accordingly not authenticated yet...
For me the code I found on internet that should resolve this problem is this one:
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.csrf().disable()
.antMatcher("/admin/**")
.authorizeRequests() //
.anyRequest().authenticated() //
.and()
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
You can find this code in the security config.
To exclude urls for the security filter, you should override the other configure method that accepts a WebSecurity as an argument and specify the url paths to ignore...
eg.
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/login/**");
}
Another option you could look into is to configure form based login in spring security...
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
...
.logout();
}
It also looks like you're custom coding oauth2 authentication. Have you looked at what spring security 5 provides out of the box for securing urls with jwt tokens?
Check out the documentation at
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2resourceserver.

spring-boot Error: Exceeded maxRedirects. Probably stuck in a redirect loop

I am trying to perform JWT auth in spring boot and the request are getting stuck in redirect loop.
JWTAuthenticationProvider
#Component
public class JwtAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
#Autowired
private JwtUtil jwtUtil;
#Override
public boolean supports(Class<?> authentication) {
return (JwtAuthenticationToken.class.isAssignableFrom(authentication));
}
#Override
protected void additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
}
#Override
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
JwtAuthenticationToken jwtAuthenticationToken = (JwtAuthenticationToken) authentication;
String token = jwtAuthenticationToken.getToken();
JwtParsedUser parsedUser = jwtUtil.parseToken(token);
if (parsedUser == null) {
throw new JwtException("JWT token is not valid");
}
UserDetails user = User.withUsername(parsedUser.getUserName()).password("temp_password").authorities(parsedUser.getRole()).build();
return user;
}
JwtAuthenticationFilter
public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
super("/**");
this.setAuthenticationManager(authenticationManager);
}
#Override
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
return true;
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
String header = request.getHeader("Authorization");
if (header == null || !header.startsWith("Bearer ")) {
throw new JwtException("No JWT token found in request headers");
}
String authToken = header.substring(7);
JwtAuthenticationToken authRequest = new JwtAuthenticationToken(authToken);
return getAuthenticationManager().authenticate(authRequest);
}
#Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, Authentication authResult)
throws IOException, ServletException {
super.successfulAuthentication(request, response, chain, authResult);
chain.doFilter(request, response);
}
}
SecurityConfiguration
#Configuration
#EnableWebSecurity(debug = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private JwtAuthenticationProvider jwtAuthenticationProvider;
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(jwtAuthenticationProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().antMatchers("/secured-resource-1/**", "/secured-resource-2/**")
.hasRole("ADMIN").antMatchers("/secured-resource-2/**").hasRole("ADMIN").and().formLogin()
.successHandler(new AuthenticationSuccessHandler()).and().httpBasic().and().exceptionHandling()
.accessDeniedHandler(new CustomAccessDeniedHandler()).authenticationEntryPoint(getBasicAuthEntryPoint())
.and()
.addFilterBefore(new JwtAuthenticationFilter(authenticationManager()),
FilterSecurityInterceptor.class)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
#Bean
public CustomBasicAuthenticationEntryPoint getBasicAuthEntryPoint() {
return new CustomBasicAuthenticationEntryPoint();
}
}
MainController
#RestController
public class MainController {
#Autowired
private JwtUtil jwtUtil;
#GetMapping("/secured-resource-1")
public String securedResource1() {
return "Secured resource1";
}
}
When I hit the endpoint with the valid JWT token, the code goes in a loop from Filter to provider class and ends in Error:
Exceeded maxRedirects. Probably stuck in a redirect loop http://localhost:8000/ error.
Debug logs shows the following error:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: Cannot call sendError() after the response has been committed] with root cause
java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
Any suggestions what am I missing here.
Thanks in advance.
I believe the the reason for this is because you have not actually set the AuthenticationSuccessHandler for the bean JwtAuthenticationFilter, since it is not actually set it will keep looping around super and chain and later when the error needs to be sent since response is already written in super() chain.doFilter will fail because once the response is written it cannot be again written hence the error call sendError() after the response has been committed.
To correct this in your SecurityConfiguration before setting this
.addFilterBefore(new JwtAuthenticationFilter(authenticationManager()),
FilterSecurityInterceptor.class)
Instantiate the filter and set it's success manager like so
JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager()),FilterSecurityInterceptor.class);
jwtAuthenticationFilter.setAuthenticationSuccessHandler(new CustomAuthenticationSuccessHandler());
Now use the above variable to set the filter.
This is a great reference project: https://gitlab.com/palmapps/jwt-spring-security-demo/-/tree/master/.
I solved this problem with another approach.
In the JwtAuthenticationFilter class we need to set authentication object in context and call chain.doFilter. Calling super.successfulAuthentication can be skipped as we have overridden the implementation.
#Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, Authentication authResult)
throws IOException, ServletException {
//super.successfulAuthentication(request, response, chain, authResult);
SecurityContextHolder.getContext().setAuthentication(authResult);
chain.doFilter(request, response);
}
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
super("/**");
this.setAuthenticationManager(authenticationManager);
//this.setAuthenticationSuccessHandler(new JwtAuthenticationSuccessHandler());
}

Why doesn't SpringBoot Security return any response to REST client although the authentication is done

I'm trying to implement JWT auth with a REST API in SpringBoot. When I debug my code, I see that the JWT Authenticator works correctly but I can't see that the JWT Authorization code is called by the Spring Security framework and there's no response sent to my REST client. Below are some parts of my code that I think are related to my problem.
I think my request is getting lost somewhere in the Spring Security flow...
WebSecurityConfig:
#EnableWebSecurity(debug = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and()
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/admin/**")
.hasRole("ADMIN")
.anyRequest()
.authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
// this disables session creation on Spring Security
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
JWTAuthenticationFilter:
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
setAuthenticationManager(authenticationManager);
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
if (!HttpMethod.POST.matches(request.getMethod())) {
throw new AuthenticationServiceException(
"Authentication method not supported: " + request.getMethod());
}
try {
JsonAuthenticationParser auth =
new ObjectMapper().readValue(request.getInputStream(), JsonAuthenticationParser.class);
System.out.println(auth.username);
System.out.println(auth.password);
UsernamePasswordAuthenticationToken authRequest =
new UsernamePasswordAuthenticationToken(auth.username, auth.password);
return this.getAuthenticationManager().authenticate(authRequest);
} catch (Exception e) {
log.warn("Auth failed!!!!!!!!!!!!");
throw new InternalAuthenticationServiceException("Could not parse authentication payload");
}
}
#Override
protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res,
FilterChain chain, Authentication auth) throws IOException, ServletException {
String token = Jwts.builder().setSubject(((User) auth.getPrincipal()).getUsername())
.claim("roles", ((User) auth.getPrincipal()).getAuthorities())
.setExpiration(new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SecurityConstants.SECRET.getBytes()).compact();
res.addHeader(SecurityConstants.HEADER_STRING, SecurityConstants.TOKEN_PREFIX + token);
System.out.println("Token:"+token);
}
JWTAuthorizationFilter
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
public JWTAuthorizationFilter(AuthenticationManager authManager) {
super(authManager);
}
#Override
protected void doFilterInternal(
HttpServletRequest req, HttpServletResponse res, FilterChain chain)
throws IOException, ServletException {
System.out.println("++++++++++++++++++++++++++++AUTHERIZATION doFilterInternal++++++++++++++++++++++");
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
System.out.println("++++++++++++++++++++++++++++AUTHERIZATION getAuthentication++++++++++++++++++++++");
}
Background
When you add a filter to the filter chain without specifying the order (http.addFilter(...)), the comparator HttpSecurity uses to determine its order in the chain looks at the filter's parent class. UsernamePasswordAuthenticationFilter comes before BasicAuthenticationFilter (see FilterComparator).
The request comes in, reaches JWTAuthenticationFilter, and "ends" in the successfulAuthentication() method.
Solution
Continue the filter chain in JWTAuthenticationFilter:
#Override
protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res,
FilterChain chain, Authentication auth)
throws IOException, ServletException {
// ...
chain.doFilter(req, res);
}

Spring Security UsernamePasswordAuthenticationFilter: How to access Request after a failed login

I am implementing a login page using Angular 7 and Spring Boot and I am with an issued processing a failed login. Basically I want to lock for a specific amount of time the login after X login attempt failures.
HttpSecurity configuration
#Override
protected void configure(HttpSecurity http) throws Exception {
logger.info("#### Configuring Security ###");
JWTAuthenticationFilter jwtAuthenticationFilter = new JWTAuthenticationFilter(authenticationManager());
jwtAuthenticationFilter.setFilterProcessesUrl("/rest/users/authenticate");//this override the default relative url for login: /login
http
.httpBasic().disable()
.csrf().disable()
.authorizeRequests()
.antMatchers("/rest/", "/rest/helloworld/**").permitAll()
.anyRequest().authenticated()
.and().exceptionHandling().authenticationEntryPoint(new JwtAuthenticationEntryPoint()).and()
.addFilter(jwtAuthenticationFilter);
To process the login i created a Filter
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private static Logger logger = Logger.getLogger(JWTAuthenticationFilter.class);
private AuthenticationManager authenticationManager;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
UserDto credentials = new ObjectMapper().readValue((request.getInputStream()), UserDto.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
credentials.getUserName(),
credentials.getPassword(),
new ArrayList<>())
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
//sucessfull authentication stuff
}
#Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
logger.info("Authentication failed");
ErrorMessage errorMessage = new ErrorMessage("access_denied", "Wrong email or password.");
String jsonObject = JSONUtil.toJson(errorMessage);
//processing authentication failed attempt
UserDto credentials = new ObjectMapper().readValue((request.getInputStream()), UserDto.class);
AuthenticationService authenticationService = Application.getApplicationContext().getBean(AuthenticationService.class);
int numFailedAttemptLogin = authenticationService.authenticationFailedAttempt(credentials.getUserName());
response.setStatus(403);
PrintWriter out = response.getWriter();
out.print(jsonObject);
out.flush();
out.close();
//super.unsuccessfulAuthentication(request, response, failed);
}
}
The login is working fine with no issues. My problem is with the unsuccessfulAuthentication method. When the user enters bad credentials, a BadCredentials exception is raised and unsuccessfulAuthenticationmethod is call. Here i need to access again to the request form to extract the username and process the authentication failed attempt and I am getting the following exception
java.io.IOException: Stream closed
This is because inside the attemptAuthentication method the request inputstream is read and obviously closed.
How can i access request body information inside the unsuccessfulAuthentication?
I tried SecurityContextHolder.getContext().getAuthentication() but it is null due the authentication failure.
Does anyone have any idea?
Best Regards
After following M.Deinum suggestion i was able to create a component that listens specific Exceptions:
#Component
public class AuthenticationEventListener implements ApplicationListener<ApplicationEvent> {
private static Logger logger = Logger.getLogger(AuthenticationEventListener.class);
#Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
logger.info(String.format("Event types: %s", applicationEvent.getClass()));
if (applicationEvent instanceof AbstractAuthenticationFailureEvent) {
String username = ((AbstractAuthenticationFailureEvent) applicationEvent).getAuthentication().getName();
if (applicationEvent instanceof AuthenticationFailureBadCredentialsEvent) {
logger.info(String.format("User %s failed to login", username));
//this.handleFailureEvent(username, event.getTimestamp());
}
}
}
}
This approach is using Exceptions to drive what to do in specific scenarios. I was able to achieve something similar keep using my JWTAuthenticationFilter like this
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
UserDto credentials = new ObjectMapper().readValue((request.getInputStream()), UserDto.class);
try {
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
credentials.getUserName(),
credentials.getPassword(),
new ArrayList<>())
);
} catch (BadCredentialsException bce) {
try {
handleBadCredentials(credentials, response);
throw bce;
} catch (LockedException le) {
handleUserLocked(credentials, response);
throw le;
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
logger.info("Authentication failed");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType(MediaType.TEXT_PLAIN_VALUE);
response.getWriter().print(authException.getLocalizedMessage());
response.getWriter().flush();
}
Thak you all for your time and help, much appreciated.

Login via spring security don't work

I add to my application the following configuration class for the spring security:
#Autowired
private CustomAuthenticationProvider authenticationProvider;
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(authenticationProvider);
}
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/publico/**", "/erro/publico/**", "/bootstrap/**", "/extras/**", "/jquery/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/acesso/login").permitAll()
.loginProcessingUrl("/processaLogin").permitAll()
.usernameParameter("login")
.passwordParameter("senha")
.successHandler(new CustomAuthenticationSuccessHandler())
.failureHandler(new CustomAuthenticationFailureHandler())
.and()
.logout()
.logoutUrl("/processaLogout")
.logoutSuccessUrl("/acesso/login").permitAll();
}
which in the moment doesn't work (after I enter my login credencials, back to login page instead go to start page).
My CustomAuthenticationProvider is this:
#Autowired
private UserDetail usuario;
#Override
public Authentication authenticate(Authentication arg0) throws AuthenticationException {
System.out.println("CustomAuthenticationProvider.authenticate");
UserDetails user = usuario.loadUserByUsername(arg0.getName());
if(user.getPassword().equals(arg0.getCredentials())) {
System.out.println("yes");
Authentication auth = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), user.getAuthorities());
return auth;
}
else {
System.out.println("not");
return null;
}
}
#Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
My CustomAuthenticationSuccessHandler:
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication arg2) throws IOException, ServletException {
System.out.println("CustomAuthenticationSuccessHandler.onAuthenticationSuccess");
HttpSession session = request.getSession();
SavedRequest savedReq = (SavedRequest) session.getAttribute(WebAttributes.ACCESS_DENIED_403);
if (savedReq == null) {
if(arg2.getAuthorities().contains("admin")) {
System.out.println("admin");
response.sendRedirect(request.getContextPath() + "/privado/admin");
}
else {
System.out.println("customer");
response.sendRedirect(request.getContextPath() + "/privado/customer");
}
}
else {
System.out.println("access_denied");
response.sendRedirect(savedReq.getRedirectUrl());
}
}
My CustomAuthenticationFailureHandler
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException arg2) throws IOException, ServletException {
System.out.println("CustomAuthenticationFailureHandler.onAuthenticationFailure");
response.sendRedirect(request.getContextPath() + "/erro/login");
}
Anyone can see what's wrong with this code?
Ok, after more tests I finally figure out what this problem: I'm just missing the 'method=post' in the login page. Now it's working fine.

Resources