Web API In Memory Integration Testing - Authentication between two services

asp.net-web-api2 entity-framework-6 in-memory integration-testing owin

Accepted Answer

I've just discovered a solution to this problem after dealing with it for days. I started by relocating the integration tests into the primary Web API. After taking a step back and giving the issue more thought, I saw that all I was actually testing by building a separate solution and spinning up my user service and Web API in memory was Identity Framework rather than the API itself.

For both authorised and unauthenticated calls, my user service's integration tests are fully functional. I had the impression that I ought to be able to utilise the Web API to do the same thing and not depend on the user service.

To test the API, I reasoned that I must be able to "bypass" the [Authorize] property. After doing some research on Google, I came across the following post, which was quite helpful in getting the solution to work:

https://blogs.taiga.nl/martijn/2016/03/10/asp-net-web-api-owin-authenticated-integration-tests-without-authorization-server/

For me, the following factors were crucial:

  1. For the test, a separate http client needs to be built.

    var client = new HttpClient(_webApp.Handler) {BaseAddress = new Uri("http://localhost")};
    
  2. For the test, a separate GET call has to be written.

    token = token == string.Empty ? GenerateToken(userName, userId) : token;
    var request = new HttpRequestMessage(HttpMethod.Get, uri);
    request.Headers.Add("Authorization", "Bearer " + token);
    var client = GetAuthenticatedClient(token);
    return await client.SendAsync(request);
    
  3. The token must be created in the manner listed below. Since the User Id is collected from the request inside the controller, I also needed to create a claim for it.

    private static string GenerateToken(string userName, int userId)
    {
        var claims = new[]
        {
            new Claim(ClaimTypes.Name, userName),
            new Claim(ClaimTypes.NameIdentifier, userId.ToString()) 
        };
        var identity = new ClaimsIdentity(claims, "Test");
    
        var properties = new AuthenticationProperties { ExpiresUtc = DateTime.UtcNow.AddHours(1) };
        var ticket = new AuthenticationTicket(identity, properties);
        var format = new TicketDataFormat(_dataProtector);
        var token = format.Protect(ticket);
        return token;
    }
    

Thanks to everyone who contributed; I hope this article aids others who are dealing with similar problems.

1
6/8/2018 12:17:38 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow