I am using Spring Boot for my application. Due to a particular need, I have my own Servlet class that extends from the Spring DispatcherServlet. (And I am pretty sure that I won't be the first one that is doing this.)
Everything worked fine until I tried adding authentication/authorization. I setup the authentication/authorization as shown here:
https://github.com/spring-projects/spring-data-examples/tree/master/rest/security
I use the #PreAuthorize annotations on my REST controller methods to restrict access based on the type of operation such as GET/POST.
I get the error: "AuthenticationObject not found in SecurityContextHolder" when I try to POST something. What I did next was compare my application and a working Spring Boot Security example (as in the example above) by stepping through it to see what is happening. I discovered that in the working example, before the doService method of the DispatcherServlet is being invoked, filters such as BasicAuthenticationFilter and others come into the picture. I don't see these filters getting invoked in my application.
Due to the filters not being invoked I don't see the user information or the session-id in the request object at all in my application. I do see that in the working example though. Moreover, I see that in the working example, the request and response objects gets wrapped in a SecurityContextHolder Wrapper from the filter. Since filters don't get invoked in my application, the request/response objects never get wrapped. I suspect that the above error is related to this.
I guess that since I have my own Servlet class that extends the Spring Servlet, it is in essence saying to Spring that I will take control from there. This also means that I will have to do everything that normally Spring does for me.
My questions are :
At what point in Spring Boot do the filters get invoked and how do I achieve
this in my application before the request reaches my custom Servlet?
Do I have to inject them as Beans into my Main class ? And in what order
should they be invoked?
Thanks again,
Related
I'm working on a Spring web application (not Spring Boot) that uses Spring Security 5.3.3, Spring Security OAuth 2.5.0, and configures it like this:
http.authorizeRequests().
antMatchers(permitUrls).
permitAll().
anyRequest().
authenticated().
and().
oauth2ResourceServer().
jwt();
Our clients report occasional 401 responses which we can't find in our application logs, so we assume it's from the Spring Security itself. We would like to log authentication and authorization failures, but I'm confused as to what is the current preferred method to achieve that.
A quick search reveals 4 paths:
custom AuthenticationFailureHandler (seems like this one is only available in FormLoginConfigurer, which isn't our case)
custom AuthenticationEntryPoint (this one is available with JWT, but OAuth2AuthenticationEntryPoint which I was going to extend is deprecated with an unhelpful message). I could try using HttpStatusEntryPoint instead, but I'd like to avoid changing the current behavior of my app, just want to add logging.
custom Filter (probably, not the cleanest path)
AuditApplicationEvents — looks beautiful, but seems like it's for Spring Boot only.
Could anyone provide me with some guidance on this?
I suggest activating the logger of org.springframework.security by changing its log level to DEBUG.
Based on your log tools (log4j2, logback, ...) create a logger in your log configurations with name org.springframework.security and level DEBUG.
Moving from container-managed authentication to the Spring Security plugin in a Grails 3.1.9 app. In the container-managed world, our Grails interceptors executed AFTER authentication for a secured resource. However, with Spring Security, the interceptors (with before() logic) execute with the following sequence:
Call to a secured resource
Interceptor stack intercepts the request, returns true
Redirected to form login page
Successful authentication
Redirection to the requested resource
We have interceptors that should only fire for authenticated users. Is there a way to have interceptors executed between step 4 & 5 instead of this flow? Or is this where our interceptor logic needs to move into Spring Security filters?
It's a little more clear if you look at the flow in a 2.x app since there's a web.xml file where it's more clear what order several of the parts run in, but it's basically the same in 2.x and 3.x.
The plugin's filter chain is registered as one filter and it's configured to run after the grailsWebRequest filter but before the GrailsDispatcherServlet. This is to support annotated controllers that may have URL mappings that are different from the default (e.g. PersonController.show() may map to /person/show but the app could have mapped it to any valid uri (and combination of REST verb(s)), so I need to be able to search the compiled URL mapping instances to figure out what controller action will run for the current request. In the filter, I know what URL is being requested, but not what security rule(s) to apply; if everything was url-based it would be simple and precompiled at startup, but with annotated controllers, I only know what rules apply to controller methods.
The servlet runs after the filters, and that's where the controller is determined and invoked. Interceptors (and Grails filters (not to be confused with servlet Filters) in 2.x) are actually Spring HandlerInterceptors that get composed along with a 'handler' into a HandlerExecutionChain. This is generic enough to work with any type of request but in practice the handler is a controller, so the scope is much narrower than if it were a servlet Filter.
So to get back to your actual question, your best option is to do the work in a filter that's added to the Spring Security filter chain. These are pretty simple to implement and the process is described in the plugin docs.
Here is my issue: I don't want to use any of spring security core filter when a user is using the API (basically, all /myapi/** request), to avoid creating a useless session. The api is based on oauth token.
So, I'm using the plugin spring-security-core for the user authentication, and I added, in my Config.groovy file,
grails.plugins.springsecurity.filterChain.chainMap = [
'/myapi/**': 'JOINED_FILTERS,-securityContextPersistenceFilter,-logoutFilter,-authenticationProcessingFilter,-securityContextHolderAwareRequestFilter,-rememberMeAuthenticationFilter,-anonymousAuthenticationFilter,-exceptionTranslationFilter',
'/**':'JOINED_FILTERS'
]
Basically, from what I understood, it shouldn't go throught any spring security filter for all /myapi/something, but, actually, it goes throught all the filters as it creates a session (i don't have anything for session in /myapi/something.
But, according to http://grails-plugins.github.com/grails-spring-security-core/docs/manual/guide/16%20Filters.html
So you need a /** catch-all rule at the end for URLs that do not match one of the earlier rules.
And that's why I don't understand why the request are still going throught all the filters for any /myapi/something.
Some testing I did, which may help:
It is not creating a session if I only have, in my Config.groovy:
grails.plugins.springsecurity.filterChain.chainMap = [
'/myapi/**': 'JOINED_FILTERS,-securityContextPersistenceFilter,-logoutFilter,-authenticationProcessingFilter,-securityContextHolderAwareRequestFilter,-rememberMeAuthenticationFilter,-anonymousAuthenticationFilter,-exceptionTranslationFilter'
]
But it's also not creating a session for the other urls, not using any other filter, which causes the application not to work of course. This example was just to be sure that the session was not created by the /myapi/something request
If i just have:
grails.plugins.springsecurity.filterChain.chainMap = [
'/myapi/**': 'JOINED_FILTERS'
]
Then, it goes throught all the filters for all /myapi/something request and create a session. It doesn't use any filter for the other request. It is the excepted behavior.
Thanks a lot for your help, I have been fighting with that for some times now, and any ideas would be more than welcome!
Thanks a lot! Have a good day.
Yup, I'm suffering from the exact same problem! Although I don't use JOINED_FILTER, I set the filter explicitly like this:
grails.plugins.springsecurity.filterChain.chainMap = [
'/apitest/**': 'requestContextAttributesFilter,sessionPreventionFilter,objectRepositoryCreationFilter',
'/api/**': 'requestContextAttributesFilter,sessionPreventionFilter,objectRepositoryCreationFilter,apiAuthenticationFilter',
'/**': 'requestContextAttributesFilter,securityContextPersistenceFilter,aisAuthenticationProcessingFilter'
]
The last filter of the catch-all rule gets executed when I access the '/apitest/*' URL. I could not reproduce this issue when I created a simple Grails project with a few dummy filters, which only did a println, and a similar chain map. For the simple test project, the filters acted as expected. Since there doesn't seem to be a proper logging when which filter gets executed and why, it is quite difficult to pinpoint the problem. Very strange...
UPDATE:
I was able to reproduce this error using the Spring Security Core plugin version 1.2.7.2. However, this bug seems to be fixed with version 1.2.7.3!
See: http://jira.grails.org/secure/ReleaseNote.jspa?projectId=10229&version=13100
Using version 1.2.7.3 seems to solve this issue.
I am using Spring Security 3.0.5 and Camel 1.5 (yes, very old but we don't have time to update right now).
In this particular scenario I am uploading a file which hits a Spring Controller which then redirects the request body (which is XML) to an endpoint which is a method in another class. Here is the issue: I had a tester perform an upload but when the GUI listing of files came back it had another person's name as the person who uploaded the file. During debugging I found that in the first Spring Controller the SecurityContext is correct in that it is indeed the credentials for the person performing the upload. After the Camel redirect though the SecurityContext was for another user who happened to have a session in the web app. Obviously this is not good.
So two questions:
Does anybody know what to do or if there is anything I can do using Camel 1.5 to fix this issue?
Why would the credentials of another user from another session be in this session? This question is regardless of Camel.
What http are you using? Can you check if there is a single thread only processing the request at all time, or is multiple threads involved?
And btw Camel 1.5 is EOL, and not support at all anymore.
I'm writing a pair of aspects. The first is to trap usernames when users successfully authenticate against my web app and the other is to trap when they explicitly logout. I'm having trouble finding Spring framework methods which are called only once and which will therefore let me capture this information.
We are using a basic Spring Security 3.0 configuration, with our only additions being to provide our own UserDetailsService implementation.
Can anyone help?
It turns out that this was completely the wrong way to do this. Spring has a set of baked-in ApplicationEvent classes which you can create ApplicationListeners to catch. Strangely, there seems to be no "LogoutEvent" but there are the very useful AuthenticationSuccessEvent, AbstractAuthenticationFailureEvent, HttpSessionCreationEvent and HttpSessionDestroyedEvent. Most interesting of all is the RequestHandledEvent.
To catch these I created my own bean which implemented
org.springframework.context.ApplicationListener;
and overrode
public void onApplicationEvent(ApplicationEvent appEvent)
In this I just if/else my way through the various appEvent types and take the appropriate actions to track users and sessions.