5

I have a working spring-security configuration which wraps my jersey-based REST endpoints and allows method-level access.

Sample project with everything needed to reproduce the problem quickly: https://github.com/pulkitsinghal/dummy-rest-api

// Server-Side jersey resource
@GET
@Path("/protected/myendpoint/")
@PreAuthorize("hasRole('DUMMY')")
public String getMyEndpoint(){
    return "blah";
}

But when writing sanity tests for the protected endpoint, I ran into the following exception which only occurs in the unit tests:

Caused by:
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException:
An Authentication object was not found in the SecurityContext

Here is what the JerseyTest based Unit Test class looks like:

@Test
public void testProtectedEndpoint() {
    WebResource webResource = resource();
    webResource.addFilter(new HTTPBasicAuthFilter("username", "password"));
    String responseMsg = webResource
                .path("protected/myendpoint/")
                .get(String.class);
    System.out.println(responseMsg);
}

Has anyone else run into this problem when setting up a JerseyTest for a spring-security protected endpoint? What can be done about it?

I remotely see some connection here: Spring Test & Security: How to mock authentication? but I am not at a level where I could make heads or tails of what's going on in that thread. Thoughts?

Community
  • 1
  • 1
pulkitsinghal
  • 3,855
  • 13
  • 45
  • 84
  • 1
    Can you post the full stack trace of the exception as well your Spring Security configuration? Also, which versions of Spring, Spring Security, and Jersey are you using? – John R Jan 03 '14 at 21:31
  • Added a working sample project that demonstrates the problem when the unit test is run, here: https://github.com/pulkitsinghal/dummy-rest-api – pulkitsinghal Jan 25 '14 at 17:56
  • Is this sort of unit test, something that just won't work on `GrizzlyWebTestContainerFactory`, no matter what? – pulkitsinghal Jan 26 '14 at 16:35

2 Answers2

0

JerseyTest is running on Grizzly on default, and your restful web service given a spring security setting on Tomcat--as a sample. So, please check both servlet server has the same setting.

feuyeux
  • 1,158
  • 1
  • 9
  • 26
  • That is quite interesting! Please help me understand, if I kick off the JerseyTest and it starts in Grizzly, why would the spring-security configuration be launched in tomcat instead? I was pretty sure that grizzly was responsible for starting both the server and the test. – pulkitsinghal Nov 15 '13 at 16:42
  • If grizzly is your production server and staging server, that's good, and no need kind of tomcat. So, please check the setting on subclass of JerseyTest if it's same with the production setting. – feuyeux Nov 16 '13 at 16:38
  • This might help you : https://github.com/alesaudate/kickstart-springjerseyhibernate/blob/master/src/test/java/com/alesaudate/samples/test/client/PersonClientTest.java – Muthu Jan 08 '14 at 10:47
0

Ideally I wanted a separate container like GrizzlyWebTestContainerFactory as the test webserver when running tests via the default maven lifecycle: mvn clean test

But I suppose, if there is no right answer to this then as a workaround using the ExternalTestContainerFactory as the test webserver will have to do:

$ mvn clean package -DskipTests && (nohup foreman start &)
$ mvn -Djersey.test.containerFactory=com.sun.jersey.test.framework.spi.container.external.ExternalTestContainerFactory \
  -Djersey.test.port=5000 \
  -Djersey.test.host=localhost \
  test

NOTE: for those unfamiliar with foreman start just think of it as tomcat start for all intensive purposes in this use case.

This still prevents checkins to master if tests are broken and spring-security doesn't barf on the external tomcat so it works out I suppose. Its a bit annoying to always go find the pid of the tomcat/java background process and kill it for clean up afterwards.

pulkitsinghal
  • 3,855
  • 13
  • 45
  • 84