How can I find which AuthenticationProvider/Filter failed in my SimpleUrlAuthenticationFailureHandler? - spring-boot

(I am using Spring Boot 1.3.5 and Spring Security 4.2.2).
I have multiple custom AbstractAuthenticationProcessingFilters and AuthenticationProviders in my application, and they each can throw different types of exceptions that all should result in a failed authentication. So I wrote a class which implements AuthenticationFailureHandler and implements
onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response, AuthenticationException exception)
to listen for failed authentication attempts.
My question - is it possible within my SimpleUrlAuthenticationFailureHandler to know which AbstractAuthenticationProcessingFilter failed? I'm able to get the specific exception that was thrown since the last parameter is AuthenticationException, but I also need to know the AbstractAuthenticationProcessingFilter that failed to determine how to proceed.

Would it work to wire a separate instance of SimpleUrlAuthenticationFailureHandler for each filter? It might be simpler than one handler that knows everything, e.g.:
MyFirstFilter first = new MyFirstFilter();
first.setAuthenticationFailureHandler
(new SimpleUrlAuthenticationFailureHandler(...));
MySecondFilter second = ...
http
.addFilter(first) ...
If not, you could possibly write something to the request object.
Instead of extending AbstractAuthenticationProcessingFilter, it might work to instead just extend OncePerRequestFilter, which may give you a flexibility that the AAPF template doesn't give you.

Related

HttpServletRequest throws error when used within Aspect

I have a method which has an aspect. When I try to #Autowire HttpServletRequest, and use request.getHeader(something), I get this error -
No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
How do I fix this? I tried using RequestContextHolder, but upon debugging I still see null. How do I use the RequestContextListener when my project has no web.xml.
Request Header can be accessed using HttpServletRequest below way.
private static HttpServletRequest getRequest() {
return((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
}
public static String getApiTraceId() {
return getRequest().getHeader(something);
}
Aspect annotations spins a new thread which is different from the one httpservlet is available in. This is why request was not available within the #ASpect. To resolve it, call the request object BEFORE the aspect method, cache it and call the same method as before.

How to reject access in Spring after successful authentication

I'm implementing some REST services in Spring and need to reject, in some cases, a successful login of a user.
I have implemented my UserDetailsService and programmed the loadUserByUsername(String username) method, but, when a user gets correctly authenticated, I need to do another validation and, if it fails, reject the access.
To do so I have implemented a listener to detect correct authentications:
#Component
public class LoginSuccessListener implements ApplicationListener{
#Autowired
LicenseControlService licenseControlService;
#Override
public void onApplicationEvent(InteractiveAuthenticationSuccessEvent e){
User user = (User)e.getAuthentication().getPrincipal();
//Here I want to reject the access because of whatever logic
}
I need to be sure to apply the logic which might reject the access when the user gets correctly authorized, that's why I need to put the logic when I receive this event.
Is there any way to do that?
Im posting the solution I have adopted in case someone needs the same behaviour:
What I did was, at the class which implements the UserDetailsService, when returning the User class, instantiate it with a false at the enabled property... that returns a 401 to the requester.
I also implemented a CustomAuthenticationEntryPoint which extends BasicAuthenticationEntryPoint, and with an overriden comence method. That method is called whenever Spring is returning an authentication error, so, in this method, I can query the type of the AuthenticationException and decide and modify the returned status according to it.

Configuring Spring WebSecurityConfigurerAdapter to use exception handler

Spring Boot here. I just read this excellent Baeldung article on Spring Security and implementing basic auth with it. I'm interested in implementing it for a simple REST service (so no UI/webapp) that I need to build.
I'm particularly interested in the BasicAuthenticationEntryPoint impl. In this impl's commence override, the author:
Adds a WWW-Authenticate header to the response; and
Sets the HTTP status code on the response; and
Writes the actual response entity directly to the response; and
Sets the name of the realm
I want to follow this author's example to implement basic auth for my app, but I already have a perfectly functioning ResponseEntityExceptionHandler working for my app:
#ControllerAdvice
public class MyAppExceptionMapper extends ResponseEntityExceptionHandler {
#ExceptionHandler(IllegalArgumentException.class)
#ResponseBody
public ResponseEntity<ErrorResponse> handleIllegalArgumentExeption(IllegalArgumentException iaEx) {
return new ResponseEntity<ErrorResponse>(buildErrorResponse(iaEx,
iaEx.message,
"Please check your request and make sure it contains a valid entity/body."),
HttpStatus.BAD_REQUEST);
}
// other exceptions handled down here, etc.
// TODO: Handle Spring Security-related auth exceptions as well!
}
Is there any way to tie Spring Security and Basic Auth fails into my existing/working ResponseEntityExceptionHandler?
Ideally there's a way to tie my WebSecurityConfigurerAdapter impl into the exception handler such that failed authentication or authorization attempts throw exceptions that are then caught by my exception handler.
My motivation for doing this would be so that my exception handler is the central location for managing and configuring the HTTP response when any exception occurs, whether its auth-related or not.
Is this possible to do, if so, how? And if it is possible, would I need to still add that WWW-Authenticate to the response in my exception handler (why/why not)? Thanks in advance!
I don't think that this is possible. Spring security is applied as a ServletFilter, way before the request ever reaches any #Controller annotated class - thus exceptions thrown by Spring Security cannot be caught by an exception handler (annotated with #ControllerAdvice).
Having had a similar problem, I ended up using a custom org.springframework.security.web.AuthenticationEntryPoint which sends an error, which in turn is forwarded to a custom org.springframework.boot.autoconfigure.web.ErrorController

How can I extend the parameters of the OAuth2 authorization endpoint?

I'm having some trouble regarding the authorization endpoint of my Spring based OAuth2 provider. I need more information from the client than there is currently possible. This is what I want to achieve:
I need the custom parameter in the authentication process later on. Is there any simple way to extend the default parameters with my custom one or do I need to implement a certain class myself?
Did some research on how the authentication endpoint works in the current Spring code. I found that the Authorization Endpoint uses a method named authorize that takes all the parameter that are being set and converts then into an AuthorizationRequest. While looking further into the AuthorizationRequest class I found that it holds a map with extensions that is being filled throughout the authorization process. But it does not seem to get filled with my custom parameter (as shown above). This is in fact by only looking at the code, so I might be wrong.
Would it be a good idea to extend the AuthorizationEndpoint with my custom implementation or is there a better and cleaner way to do this?
Update #1 (07-10-2015)
The place where I'd like to use the custom parameter is in my own implementation of the AuthenticationProvider. I need to information to be available inside the authenticate method of this class.
Update #2 (07-10-2015)
It seems that the AuthorizationProvider gets called before the AuthorizationEndpoint. This means that the custom parameter is obtained after the class where I need it (so that's too late).
Maybe I can get the referral Url by either extending part of the Spring security classes or by obtaining it in the HTML through JavaScript. Is this a good idea or should I use another approach?
So I managed to fix the problem myself by searching some more on Google.
What you need to do is speak to the HttpSessionRequestCache to get the referral URL. This is how I solved it in my own implementation of the AuthenticationProvider
#Component
public class CustomProvider implements AuthenticationProvider {
#Autowired
private HttpServletRequest httpRequest;
#Autowired
private HttpServletResponse httpResponse;
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(httpRequest, httpResponse);
logger.info("Referral URL: " + savedRequest.getRedirectUrl());
logger.info("Parameters: " + savedRequest.getParameterMap().keySet().toString());
}
}
This will print out the URL of the request that was called before heading to the login page of spring security. The second log method prints out the parameters that where found in this URL. This question and answer helped me in creating a solution for my problem.

How to get source address / ip from inside ContainerResponseFilter

I'm writing a logging filter that logs all HTTP requests / responses for a web app running in Jersey. ContainerResponseFilter seems to a straight forward solution and I've managed to get it to work.
Next step is to log the IP of the requests. Is there a way to do that from inside the ContainerResponseFilter ?
Short answer:
#Provider
public class YourContextFilter implements ContainerRequestFilter {
#Context
private HttpServletRequest sr;
#Override
public synchronized void filter(ContainerRequestContext request) throws IOException {
/*
* Returns the Internet Protocol (IP) address of the client or
* last proxy that sent the request. For HTTP servlets, same as
* the value of the CGI variable REMOTE_ADDR.
*/
String ip = sr.getRemoteAddr();
// ... log it ...
}
}
EDIT
(regarding the wish for a more detailed answer)
Afaig:
The #Context annotation allows to inject JAX-RS–specific components (one might say you are able to inject contextual information objects). JAX-RS itself is a Java based specification for RESTful Web Services over HTTP protocol. So we are able to inject stuff like:
javax.ws.rs.core.UriInfo
javax.ws.rs.core.Request
javax.ws.rs.core.SecurityContext
and also
javax.servlet.http.HttpServletRequest
In the IOC Chapter of the Jersey docs, you will find these notes:
[...] Jersey implementation allows you to directly inject HttpServletRequest instance into your JAX-RS components [...] - https://jersey.java.net/nonav/documentation/latest/user-guide.html#d0e2401
[...] The exception exists for specific request objects which can injected even into constructor or class fields. For these objects the runtime will inject proxies which are able to simultaneously server more request. These request objects are HttpHeaders, Request, UriInfo, SecurityContext. These proxies can be injected using the #Context annotation. [...]
[...] When deploying a JAX-RS application using servlet then ServletConfig, ServletContext, HttpServletRequest and HttpServletResponse are available using #Context. [...]
And if you do so, you inject in fact a Proxy named org.apache.catalina.connector.RequestFacade (link). This proxy functioned as your direct hotline to your Coyote (HTTP Connector) and thereby to the Coyote request object (link).
Hope this was helpful somehow :) - Have a nice day.

Resources