How to make a non web thread run with the Spring Security Anonymous Use? - spring

I am using Spring Security 3.1 and I have some code which I execute on web application strartup from the init method of a Servlet. Problems is that there is no valid Authentication object at the time my servlet init method execute. My servlet is configured to run after the Spring has been initialized and spring security is full configured.
How do I make the code in my init method run as the anonymous user in spring security?

How about:
SecurityContextHolder.getContext().setAuthentication(new AnonymousAuthenticationToken(key, login, authorities))
where any non-empty string should do as a key, login like "anonymous", authorities - whichever you want him to have, at least one.

Related

SecurityContext is not getting cleared when using SpringBootTest with TestNG

I am working on a SpringBoot application. I am running integration tests on REST APIs using SpringBooTest and TestNG. It is a stateless application. Sessions are not stored.
Context
I have filter that explicitly sets the authentication object into SecurityContext like below
Authentication authentication = new UsernamePasswordAuthenticationToken(contextUser, "", null);
SecurityContextHolder.getContext().setAuthentication(authentication);
// Continue to app.
After this point, I am not using any authentication manager as the token is already validated. I am not explicitly clearing the security context any where.
Problem
When I run a couple of tests from SpringBootTest, the second test still has access to security context set in the first test. When I ran the test in debug mode, I can see SecurityContextHolder.clearContext(); getting called from SecurityContextPersistenceFilter which means context should be cleared.
How do I solve this issue? I would think security context should be always cleared after the request is complete and should not be available for the next test.
I had to set a FilterChainProxy like below for the filters to get executed in Spring Integration test, which would take care of clearing the context.
restLoginMockMvc = MockMvcBuilders.standaloneSetup(loginResource).setControllerAdvice(exceptionTranslator)
.apply(springSecurity(springSecurityFilterChain)).build();

Authentication object not found thrown by DispatcherServlet before #Preauthorize spring security annotation is applied

When i am trying to use #PreAuthorize("#accessControl.hasActivity('abc')") on spring controller method i am getting Authentication object was not found in security context.
After debugging found that DispactcherServlet is throwing this exception.
i have set SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_THREADLOCAL);
when i first create Authentication object and set in security context
Also tried with SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); but no luck still it does not work.
I am not able to understand why spring is servlet is throwing this exception
First, doing authentication in a Spring MVC interceptor is odd. Consider using a filter before DispatcherServlet. There is a lot of documented examples.
Secondly, SecurityContextHolder.setStrategyName re-initializes the strategy and possibly makes all previously authentications inaccessible so you must only call it once (if any time), before any authentication is made.
Thirdly, if you want to set the current authentication to be used by #PreAuthorize and are sure what you are doing, use SecurityContextHolder.getContext().setAuthentication(anAuthentication);. In most cases, there is a suitable filter in the API that already does this for you.

An Authentication object was not found in the SecurityContext

I have an application exporting web services, with a configured Spring Security SecurityFilterChain (with SecurityContextPersistenceFilter among others, which is required for the rest).
My application also uses Spring Security to secure method invocations.
I have following error when method security is triggered:
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
The 2nd part requires an Authentication in SecurityContextHolder as showed in org.springframework.security.access.intercept.AbstractSecurityInterceptor (line 195):
SecurityContextHolder.getContext().getAuthentication();
But, SecurityContextPersistenceFilter removes it before method invocation is triggered, as shown in
org.springframework.security.web.context.SecurityContextPersistenceFilter (line 84)
SecurityContextHolder.clearContext();
What can I do to have this object in SecurityContextHolder when method invocation is triggered?
Thank you in advance.
I'm using Spring Security 3.0.8-RELEASE
SecurityContextHolder.clearContext() will be called only after request processing completion. So normally all your application logic code will be executed before this line, and there is no problem at all. But the problem may be present if you execute some new thread in your code (by default security context will be not propogated). If this is your case then you can try to force context propogation to child thread. If you use only one thread then make sure that all your code is covered by spring security filter chain (may be you have some custom filter that executed around spring security filter chain?).
OK, my application is placed over Apache CXF DOSGi 1.4 to generate REST endpoints. Apache CXF interceptors cause an unexpected behaviour and SecurityContextHolder.clearContext() is called before finishing the request processing.
More information about this bug can be found here.

How to test REST in spring app with spring security

I've got spring web application with jersey rest services. However rest is secured via spring security and login process is very hard to perform from unit test code. I'd like to test rest services with whole spring security disabled. Is it even possible?
One of the advantages of annotation based web services is that you can unit-test them easily.
class WebServiceEndpoint {
#Path("/foo/{fooId}")
#POST
#Produces({ MediaType.APPLICATION_XML })
public Response doFoo(#PathParam("fooId") Integer fooId) {
/// ... web service endpoint implementation
}
}
If you're using Spring's servlet filter for security, then there shouldn't be any security-related code in the doFoo method, so you can just create a new WebServiceEndpoint class and call the method. So that's one way of 'disabling' security.
When you say the login process is 'hard', what do you mean? If you've succeeded in logging in once, then you can just reuse the same code in your other unit tests (e.g. in a #Before method).
Just test it as a pojo. Pass in whatever, return whatever, don't load an app context at all - that would be an integration test.
The ability to easily test functionality without the framework loaded is one of the key advantages of spring.
You don't say what's "hard," so I'm assuming that you've got something in your REST service, i.e. in the java method that you want to test, which requires authentication results. Spring has utilities for mocking the authentication results. For example, you can do the following in a #Before setup method:
Object principal = null; // fix this
Object credentials = null; // fix this
Authentication auth = new org.springframework.security.authentication.TestingAuthenticationToken(principal, credentials);
SecurityContextHolder.getContext().setAuthentication(auth);
But again, you haven't said what problem you're actually trying to solve...

Get Spring Principal User From HTTPSession From a Servlet

I have a web application that is using Spring 3.* and I have a Flash component inside my web application that needs to POST to a Servlet. Inside the Servlet's doPost method I want to check the Spring application context to ensure there is an authenticated session, is this possible?
Well it is very simple, just use
Authentication auth = SecurityContextHolder.getContext().getAuthentication();

Resources