I'm implementing new Spring Authorization server (spring-security-oauth2-authorization-server version 1.0.0). I have created following two classes to handle exceptions:
public class RestExceptionTranslationFilter implements AuthenticationFailureHandler {
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
// Code to handle the exception
}
}
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authenticationException) throws IOException, ServletException {
// Code to handle the exception
}
}
I have registered both of them like this:
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
...
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer();
authorizationServerConfigurer.tokenEndpoint(tokenEndpoint ->
((OAuth2TokenEndpointConfigurer)tokenEndpoint).errorResponseHandler(new RestExceptionTranslationFilter())
);
...
http.exceptionHandling(exceptions ->
exceptions.authenticationEntryPoint(new RestAuthenticationEntryPoint()));
}
Now I'm able to handle the OAuth2AuthenticationException exceptions and other exceptions and to return the response that my implementation requires. For example, this exception is handled correctly:
org.springframework.security.oauth2.core.OAuth2AuthenticationException: OAuth 2.0 Parameter: grant_type
at org.springframework.security.oauth2.server.authorization.web.OAuth2TokenEndpointFilter.throwError(OAuth2TokenEndpointFilter.java:260) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]
at org.springframework.security.oauth2.server.authorization.web.OAuth2TokenEndpointFilter.doFilterInternal(OAuth2TokenEndpointFilter.java:159) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]
But, what's confusing me, and I cant solve it, why the same OAuth2AuthenticationException exception is not handled by this configuration in case when its thrown like this from ClientSecretAuthenticationProvider:
org.springframework.security.oauth2.core.OAuth2AuthenticationException: Client authentication failed: client_id
at org.springframework.security.oauth2.server.authorization.authentication.ClientSecretAuthenticationProvider.throwInvalidClient(ClientSecretAuthenticationProvider.java:151) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]
at org.springframework.security.oauth2.server.authorization.authentication.ClientSecretAuthenticationProvider.authenticate(ClientSecretAuthenticationProvider.java:99) ~[spring-security-oauth2-authorization-server-1.0.0.jar:1.0.0]
Is it possible to handle this exception and how as I would really like not to disclose the message "error": "invalid_client" to the possible attackers?
Related
I'm working on springboot project and we are using openId keycloak for authentication. I'm delaing with Multitenancy concept too. I want to sent custom header as request or either response and the same should be captured in APM as metadata. My current approach is as follows:
public class PreAuthFilter extends KeycloakPreAuthActionsFilter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
((HttpServletResponse) response).addHeader("X-Realm",realm);
super.doFilter(request, response, chain);
}
But with above code i'm getting multiple response metatdata in APM
http.response.headers.X-Realm.0
http.response.headers.X-Realm.1
http.response.headers.X-Realm.2
http.response.headers.X-Realm.3
My expectation was single realm in APM Metadata
http.response.headers.X-Realm = "value"
I think SimpleHttpFacade is getting intialized during resolving deployment multiple times hence adding the response.
Need Suggestion
Thanx.
It appears this could be that the issue is more likely related to your application context spring and filters.
Since it's spring could you try OncePerRequestFilter ?
import org.springframework.web.filter.OncePerRequestFilter;
#Named
public class ApmFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// do apm things
filterChain.doFilter(request, response);
}
#Override
public void destroy() {
}
}
I have a legacy application that is in spring 4 with UI as JSP. Need move the presentation layer from spring to react app. When I call /login with parameters it gives me an HTML, How do I change my existing spring security logic so that it returns a json response.
Here is the code snippet
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().maximumSessions(1).and().invalidSessionUrl(URLConstants.LOGIN_URL);
http.csrf().disable();
http.anonymous().disable()
.authorizeRequests().antMatchers("/")
.access("hasRole('USER') or hasRole('ADMIN') or hasRole('DC MANAGER')")
.and().formLogin() .loginProcessingUrl(URLConstants.LOGIN_URL).usernameParameter("ssoId").passwordParameter("password").and()
.rememberMe().rememberMeParameter("remember-me").tokenRepository(tokenRepository) .tokenValiditySeconds(18400).and().exceptionHandling().accessDeniedPage("/Access_Denied");
}
Write a custom AuthenticationSuccessHandler that writes your JSON and plug it into your formLogin().
.formLogin().successHandler(yourSucessHandlerBean);
Your handler could roughly look like this:
#Component
public class Securityhandler implements AuthenticationSuccessHandler {
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
// write your JSON here, directly to the HttpServletResponse
}
}
I implemented Spring Security, and a custom Authentication Failure Handler, which I use the inherited method saveException which the Documentation says
Caches the AuthenticationException for use in view rendering.
Which would be perfect for me. This is what I want, I want to access the Exception saved by the Authentication Failure Handler in the frontEnd, i.e. I want to access in the bean that made the call to Spring Security.
My ControllerBean has this piece of code:
public void login() throws ServletException, IOException {
final ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
final RequestDispatcher dispatcher = ((ServletRequest) context.getRequest()).getRequestDispatcher("/login");
dispatcher.forward((ServletRequest) context.getRequest(), (ServletResponse) context.getResponse());
FacesContext.getCurrentInstance().responseComplete();
}
Which it makes the call to my CustomAuthenticationProvider, and then if it throws an exception, my CustomAuthenticationFailureHandler catches it and has the following code:
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
if (exception instanceof FirstExternalLoginException) {
setAllowSessionCreation(true);
saveException(request, exception);
getRedirectStrategy().sendRedirect(request, response, "/externalRegister.jsf");
}
}
So when this piece of code finishes, it comes back to the line:
FacesContext.getCurrentInstance().responseComplete();
Of the controller bean. How can I access the saved exception? I have been digging around the ExternalContext but have never found any AuthenticationException (or my custom exception, which extends the AuthenticationException)
Spring boot provide its own implementation for login (POST method), if I want to maintain history(count) of successful/unsuccessful log in of users, how can I do it?
Did the following to make it working:
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler{
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
// TODO Auto-generated method stub
......
}
I am using Spring Boot to deploy a .war file to an external Tomcat Server.
I am using Ajax/Restful authentication and I have the following class that handles authentication failure:
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, exception.getMessage());
}
When I'm using the embedded Tomcat server, all goes well and upon authentication failure I get the following JSON:
{
"timestamp" : "2015-12-14T15:39:07.365+0000",
"status" : 401,
"error" : "Unauthorized",
"message" : "You have provided wrong credentials",
"path" : "/api/authentication"
}
However, when using an External Tomcat Server I get an HTML response which brings the usual Tomcat failed authentication page. Is there any way to bypass this for the External Server?
Solution was simply to not use sendError() and to provide a status code and to provide a custom exception serialization:
#Service
public class AjaxAuthenticationFailureHandler
extends SimpleUrlAuthenticationFailureHandler {
#Autowired
private ObjectMapper objectMapper;
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write(objectMapper.writeValueAsString(exception));
response.getWriter().flush();
}
}