4

I have a rest controller that requires the user to be authenticated. But when the test is run the response is always 401. I am using the "WithSecurityContext" annotation, but it does not work.

Annotation

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
@WithSecurityContext(factory = WithOAuth2AuthenticationSecurityContextFactory.class)
public @interface WithOAuth2Authentication {

    String clientId() default "temporal";

    String username() default "username";

    String[] scopes() default { "read", "write", "trust" };
}

Class implementing annotation

public class WithOAuth2AuthenticationSecurityContextFactory implements WithSecurityContextFactory<WithOAuth2Authentication> {

     @Override
     public SecurityContext createSecurityContext(WithOAuth2Authentication annotation) {
         Set<String> scopes = new HashSet<>();
         Collections.addAll(scopes, annotation.scopes());

         OAuth2Request oAuth2Request = new OAuth2Request(null, annotation.clientId(), null, true, scopes, null, null, null, null);
         Authentication auth2Authentication = new OAuth2Authentication(oAuth2Request, new TestingAuthenticationToken(annotation.username(), null, "read"));

         SecurityContext context = SecurityContextHolder.createEmptyContext();
         context.setAuthentication(auth2Authentication);
         return context;
     }
}

Unit test

    @Before
    public void setup() {
        this.mapper = new ObjectMapper();
        RestDocumentationResultHandler document =
        document("{method-name}", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()));

        this.mock = MockMvcBuilders.webAppContextSetup(this.context)
            .apply(documentationConfiguration(this.restDocumentation))
            .apply(SecurityMockMvcConfigurers.springSecurity())
            .alwaysDo(document)
            .build();
    }

    @Test
    @WithOAuth2Authentication
    public void create() throws Exception {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Accept-Language", "en");
        httpHeaders.add("Content-Type", "application/json");
        httpHeaders.add("Accept", "application/json");

        String JSON = this.mapper.writeValueAsString(new Register.Project());
        this.mock.perform(post("/project/create")
            .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
            .headers(httpHeaders)
            .content(JSON))
            .andDo(print())
            .andExpect(status().isOk());
}

The result of the test

MockHttpServletResponse:
       Status = 401
       Error message = null
       Headers = {X-Content-Type-Options=[nosniff], X-XSS-Protection=[1; mode=block], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate, no-store], Pragma=[no-cache, no-cache], Expires=[0], X-Frame-Options=[DENY], WWW-Authenticate=[Bearer realm="oauth2-resource", error="unauthorized", error_description="Full authentication is required to access this resource"], Content-Type=[application/json;charset=UTF-8]}
 Content type = application/json;charset=UTF-8
       Body = {"error":"unauthorized","error_description":"Full authentication is required to access this resource"}
       Forwarded URL = null
       Redirected URL = null
       Cookies = []
  • What is `@WithOAuth2Authentication` supposed to do? In all my tests, I'm adding a fake token to the header. – Gregg Feb 22 '17 at 21:20
  • [Reference](http://docs.spring.io/spring-security/site/docs/current/reference/html/test-method.html#test-method-withsecuritycontext) – Jonattan Velásquez Mar 01 '17 at 19:20

0 Answers0