-
-
Save jaganathanb/bc258494aaeeccf5f4422e08039e6b89 to your computer and use it in GitHub Desktop.
ASP.NET Core 2.1 - Setting up functional integration tests with authentication middleware
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.AspNetCore.Mvc.Testing; | |
using System.Net; | |
using System.Threading.Tasks; | |
using Xunit; | |
using System.Net.Http; | |
using System.Collections.Generic; | |
using Newtonsoft.Json; | |
namespace Api.FunctionalTests | |
{ | |
public class BasicTests : IClassFixture<TestWebApplicationFactory<MyWebApi.Startup>> | |
{ | |
private readonly HttpClient _client; | |
private readonly HttpClient _unauthorizedClient; | |
private readonly TestWebApplicationFactory<MyWebApi.Startup> _factory; | |
public BasicTests(TestWebApplicationFactory<MyWebApi.Startup> factory) | |
{ | |
_factory = factory; | |
_client = _factory.CreateClient(new WebApplicationFactoryClientOptions | |
{ | |
AllowAutoRedirect = false | |
}); | |
// Requests made using this HTTP client will go through the test scheme handler... | |
_client.DefaultRequestHeaders.Add("X-Test-Auth", "false"); | |
// and be considered authenticated | |
_client.DefaultRequestHeaders.Add("Authorization", "Bearer asdf1234qwerty"); | |
// this client makes requests that end up being handled by the "real" auth middleware | |
_unauthorizedClient = _factory.CreateClient(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.AspNetCore.Mvc.Testing; | |
using System.Net; | |
using System.Threading.Tasks; | |
using Xunit; | |
using System.Net.Http; | |
using System.Collections.Generic; | |
using Newtonsoft.Json; | |
namespace Api.FunctionalTests | |
{ | |
public class ClaimsTests : IClassFixture<TestWebApplicationFactory<MyWebApi.Startup>> | |
{ | |
private readonly HttpClient _client; | |
private readonly HttpClient _unauthorizedClient; | |
private readonly TestWebApplicationFactory<MyWebApi.Startup> _factory; | |
public ClaimsTests(TestWebApplicationFactory<MyWebApi.Startup> factory) | |
{ | |
_factory = factory; | |
_factory = _factory.WithWebHostBuilder(builder => | |
{ | |
builder.ConfigureServices(services => | |
{ | |
services.AddAuthentication(o => | |
{ | |
o.DefaultScheme = "TestAuthenticationScheme"; | |
}) | |
.AddTestAuthentication("TestAuthenticationScheme", "Test Auth", o => | |
{ | |
o.Identity = new ClaimsIdentity( /* pass in a Claim[] */); | |
}); | |
}); | |
}); | |
_client = _factory.CreateClient(new WebApplicationFactoryClientOptions | |
{ | |
AllowAutoRedirect = false | |
}); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.AspNetCore.Authentication; | |
using System.Security.Claims; | |
using System.Threading.Tasks; | |
using System.Text.Encodings.Web; | |
using Microsoft.Extensions.Options; | |
using Microsoft.Extensions.Logging; | |
using System; | |
using System.Linq; | |
namespace Api.FunctionalTests | |
{ | |
public class TestAuthHandler : AuthenticationHandler<TestAuthenticationOptions> | |
{ | |
public TestAuthHandler(IOptionsMonitor<TestAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) | |
: base(options, logger, encoder, clock) | |
{ | |
} | |
protected override Task<AuthenticateResult> HandleAuthenticateAsync() | |
{ | |
// if the header is provided and its value is 'true', then step aside and let the regular auth handle it | |
// a value of <anything other than 'true'> will bypass the rest of the auth pipeline | |
if (!Context.Request.Headers.TryGetValue("X-Test-Auth", out var header) || header.Contains("true")) | |
{ | |
return Task.FromResult(AuthenticateResult.NoResult()); | |
} | |
// value is false (or anything other than 'true'). Make sure they've made the effort to provide the auth header | |
// but don't bother to check the value | |
if (header.Any() && !Context.Request.Headers.TryGetValue("Authorization", out var authHeader)) | |
{ | |
return Task.FromResult(AuthenticateResult.NoResult()); | |
} | |
// otherwise, here's your auth ticket! | |
return Task.FromResult( | |
AuthenticateResult.Success( | |
new AuthenticationTicket( | |
new ClaimsPrincipal(Options.Identity), | |
new AuthenticationProperties(), | |
this.Scheme.Name))); | |
} | |
} | |
public class TestAuthenticationOptions : AuthenticationSchemeOptions | |
{ | |
public bool RequireBearerToken { get; set; } | |
// customize as needed | |
public virtual ClaimsIdentity Identity { get; set; } = new ClaimsIdentity( | |
new Claim[] | |
{ | |
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", Guid.NewGuid().ToString()), | |
new Claim("http://schemas.microsoft.com/identity/claims/tenantid", "test"), | |
new Claim("http://schemas.microsoft.com/identity/claims/objectidentifier", Guid.NewGuid().ToString()), | |
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname", "test"), | |
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname", "test"), | |
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn", "test"), | |
}, | |
"test"); | |
public TestAuthenticationOptions() {} | |
} | |
public static class TestAuthenticationExtensions | |
{ | |
public static AuthenticationBuilder AddTestAuthentication(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<TestAuthenticationOptions> configureOptions) | |
{ | |
return builder.AddScheme<TestAuthenticationOptions, TestAuthHandler>(authenticationScheme, configureOptions); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.AspNetCore.Hosting; | |
using Microsoft.AspNetCore.Mvc.Testing; | |
using Microsoft.AspNetCore.TestHost; | |
using Microsoft.Extensions.DependencyInjection; | |
using System.Linq; | |
using Microsoft.Extensions.Configuration; | |
namespace Api.FunctionalTests | |
{ | |
public class TestWebApplicationFactory<TStartup> : WebApplicationFactory<MyWebApi.Startup> | |
{ | |
protected override void ConfigureWebHost(IWebHostBuilder builder) | |
{ | |
builder.UseEnvironment("Integration"); | |
builder.ConfigureAppConfiguration((builderContext, config) => | |
{ | |
IHostingEnvironment env = builderContext.HostingEnvironment; | |
config.Sources.Clear(); | |
config.AddJsonFile($"appsettings.{env.EnvironmentName}.json", false, reloadOnChange: true); | |
}); | |
builder.ConfigureTestServices(services => | |
{ | |
services | |
.AddAuthentication(o => | |
{ | |
o.DefaultScheme = "TestAuthenticationScheme"; | |
}).AddTestAuthentication("TestAuthenticationScheme", "Test Auth", o => { }); | |
}); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment