Search code examples
asp.net-coreasp.net-core-identity

Set Authenticated User Globally for Testing in ASP.NET Core


I am working on an ASP.NET Core 2.2 with ASP.Net Core Identity project.

I would like to set the authenticated User, with its UserId, globally for testing.

It this possible?


Solution

  • For Integration Test, you could progammly login the application, save the cookies and then attach the cookies for sub-requests.

    Try to implement custom WebApplicationFactory like

    public class CustomWebApplicationFactory<TEntryPoint> : WebApplicationFactory<TEntryPoint> where TEntryPoint : class
    {
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {
            builder.ConfigureServices(services =>
            {
    
            });
            base.ConfigureWebHost(builder);
        }
        public new HttpClient CreateClient()
        {
            var cookieContainer = new CookieContainer();
            var uri = new Uri("https://localhost:44344/Identity/Account/Login");
            var httpClientHandler = new HttpClientHandler
            {
                CookieContainer = cookieContainer
            };
            HttpClient httpClient = new HttpClient(httpClientHandler);
            var verificationToken = GetVerificationToken(httpClient, "https://localhost:44344/Identity/Account/Login");
            var contentToSend = new FormUrlEncodedContent(new[]
                    {
                                new KeyValuePair<string, string>("Email", "[email protected]"),
                                new KeyValuePair<string, string>("Password", "1qaz@WSX"),
                                new KeyValuePair<string, string>("__RequestVerificationToken", verificationToken),
                            });
            var response = httpClient.PostAsync("https://localhost:44344/Identity/Account/Login", contentToSend).Result;
            var cookies = cookieContainer.GetCookies(new Uri("https://localhost:44344/Identity/Account/Login"));
            cookieContainer.Add(cookies);
            var client = new HttpClient(httpClientHandler);
            return client;
        }
        private string GetVerificationToken(HttpClient client, string url)
        {
            HttpResponseMessage response = client.GetAsync(url).Result;
            var verificationToken =response.Content.ReadAsStringAsync().Result;
            if (verificationToken != null && verificationToken.Length > 0)
            {
                verificationToken = verificationToken.Substring(verificationToken.IndexOf("__RequestVerificationToken"));
                verificationToken = verificationToken.Substring(verificationToken.IndexOf("value=\"") + 7);
                verificationToken = verificationToken.Substring(0, verificationToken.IndexOf("\""));
            }
            return verificationToken;
        }
    }
    

    And then

    public class IntegrationTestWithIdentityTest : IClassFixture<CustomWebApplicationFactory<Startup>>
    {
        private readonly HttpClient _client;
        private readonly CustomWebApplicationFactory<Startup> _factory;
    
        public IntegrationTestWithIdentityTest(CustomWebApplicationFactory<Startup> factory)
        {
    
            _factory = factory;
            _client = factory.CreateClient();
        }
    
        [Fact]
        public async Task IndexRendersCorrectTitle()
        {
            var response = await _client.GetAsync("https://localhost:44344/About");
    
            response.EnsureSuccessStatusCode();
    
            var responseString = await response.Content.ReadAsStringAsync();
    
            Assert.Contains("Send Email", responseString);
        }        
    
    }
    

    Source Code: IntegrationTestWithIdentityTest.

    If you want to mock a user which is not exist in the Identity Table, you need to define a new endpoint which will sign the user with

    public async Task<IActionResult> Login()
    {
        var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme, ClaimTypes.Name, ClaimTypes.Role);
        identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, "edward"));
        identity.AddClaim(new Claim(ClaimTypes.Name, "edward zhou"));
        //add your own claims from jwt token
        var principal = new ClaimsPrincipal(identity);
        await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, new AuthenticationProperties { IsPersistent = true });            
        return View();
    }