SheppardDigital
SheppardDigital

Reputation: 3255

Spring Boot, how to pass AuthenticationPrinciple to controller from a test?

I have a Spring Boot 2 web service. It accepts a Bearer token and uses Spring OAuth2 to go to an external URL and grab the users details using that token. I'm trying to create tests that test the implementation of the web service, but I'm struggling to figure out how to pass the AuthenticationPrinicple from a test?

Here is an example of a method in my controller;

@RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json")
    public ResponseEntity listUserUploadedFiles(@AuthenticationPrincipal Client client) {
        FileListResponse rsp = new FileListResponse(fileStorageService.getUserFiles(client.getUid()));

        return rsp.response(HttpStatus.OK);
    }

Here is my test so far;

@Test
    public void TestSimple() throws Exception {
        mockMvc.perform(get("/file"))
                .andExpect(status().isOk());
    }

Currently the test fails because the Client (AuthenticationPrinicple) is null.

How would I do this?

---- UPDATE ----

Here is my Client object, as you can see, it doesn't inherit UserDetails.

public class Client implements Serializable {

    private static final long serialVersionUID = 1L;

    private String uid;
    private String email;

    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

There is also a PrincipalExtractor bean setup.

@Bean
    public PrincipalExtractor principalExtractor() {
        return map -> {
            Client client = new Client();
            client.setUid(String.valueOf(map.get("uid")));
            client.setEmail(String.valueOf(map.get("name")));

            return client;
        };
    }

To provide a little more information on the project. This is a microservice, the user authenticates via a web application which takes place externally to this service. When calls to this server are made, a token is supplied which is verified with an authenticate server (again, external). The response from authentication server provides us with a uuid and an email field, the PrincipalExtractor maps these to a Client object, which is then passed into the controller to be used.

Upvotes: 1

Views: 800

Answers (1)

Dirk Deyne
Dirk Deyne

Reputation: 6936

You could mock your user when testing @WithMockUser.

If you use MockMvc there is no extra sec-config needed

 @RunWith(SpringRunner.class)
 @WebMvcTest(SecuredController.class)
 public class SecuredControllerWebMvcIntegrationTest {

     @Autowired
     private MockMvc mockMvc;

     @Test
     @WithMockUser(value = "user")
     public void testSimple() throws Exception {
             mockMvc.perform(get("/file"))
                 ...

if you want to use @WithMockUser in a @SpringBootTest you need extra configuration

 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
 public class SecuredControllerSpringBootIntegrationTest
      ...
      @Autowired
      private WebApplicationContext context;

       private MockMvc mvc;

       @Before
       public void setup() {
            mvc = MockMvcBuilders
                   .webAppContextSetup(context)
                   .apply(springSecurity())
                   .build();
        }
 ...

ref spring-security-integration-tests

Upvotes: 1

Related Questions