Asp.net core 使用OpenIdConnect服务器(ASOS)手动生成accesstoken
我正在一个asp.net core 1.1项目中实施,我目前正在尝试使用Microsoft.AspNetCore.TestHost.TestServer实施一些集成测试(Asp.net core 使用OpenIdConnect服务器(ASOS)手动生成accesstoken,asp.net-core,integration-testing,xunit,openid-connect,aspnet-contrib,Asp.net Core,Integration Testing,Xunit,Openid Connect,Aspnet Contrib,我正在一个asp.net core 1.1项目中实施,我目前正在尝试使用Microsoft.AspNetCore.TestHost.TestServer实施一些集成测试(xunit&moq) 我遇到的问题是手动生成一个伪accesstoken,用于为HttpClient请求填充AuthenticationHeaderValue。我一直在寻找解决这个问题的有效方法,但一直没有成功 所以我的问题是:任何人都有一个技巧,如何手动为TestServer生成accesstokens,而不必调用ASOS的令
xunit
&moq
)
我遇到的问题是手动生成一个伪accesstoken,用于为HttpClient
请求填充AuthenticationHeaderValue
。我一直在寻找解决这个问题的有效方法,但一直没有成功
所以我的问题是:任何人都有一个技巧,如何手动为TestServer生成accesstokens,而不必调用ASOS的令牌端点进行测试?而ASOS故意阻止您从任意位置创建令牌(它们只能在OpenID Connect请求期间生成),您可以直接使用底层ASP.NET核心API生成OAuth2验证中间件将接受的伪令牌:
var provider = container.GetRequiredService<IDataProtectionProvider>();
var protector = provider.CreateProtector(
nameof(OpenIdConnectServerMiddleware),
OpenIdConnectServerDefaults.AuthenticationScheme, "Access_Token", "v1");
var format = new TicketDataFormat(protector);
var identity = new ClaimsIdentity();
identity.AddClaim(new Claim(ClaimTypes.Name, "Bob le Bricoleur"));
var ticket = new AuthenticationTicket(
new ClaimsPrincipal(identity),
new AuthenticationProperties(),
OpenIdConnectServerDefaults.AuthenticationScheme);
var token = format.Protect(ticket);
我喜欢最后一种方法,但只要我不向构建器添加UseStartup(),它似乎就可以工作(刚刚收到。如果我在启动时注释掉所有令牌身份验证,则会出现众所周知的不可访问错误和未经授权)。OAuth2验证中间件不使用发现(与JWT承载中间件不同),因此,这可能不是导致此问题的原因。我确实在我的应用程序中使用了UseJwtBeareAuthentication和UseOpenIdConnectServer(我使用jwt令牌),但我还是用这些令牌进行了尝试。我将进行一些调试,看看是什么原因造成的。我无法通过直接使用生产启动找到一种干净的解决方案,因此为integration testserver创建了一个单独的启动文件。这似乎工作得很好,可以很容易地在测试之间切换角色等等。谢谢你的提示!
[Fact]
public async Task ValidTokenAllowsSuccessfulAuthentication()
{
// Arrange
var server = CreateResourceServer();
var client = server.CreateClient();
var request = new HttpRequestMessage(HttpMethod.Get, "/");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "valid-token");
// Act
var response = await client.SendAsync(request);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Fabrikam", await response.Content.ReadAsStringAsync());
}
private static TestServer CreateResourceServer(Action<OAuthValidationOptions> configuration = null)
{
var builder = new WebHostBuilder();
var format = new Mock<ISecureDataFormat<AuthenticationTicket>>(MockBehavior.Strict);
format.Setup(mock => mock.Unprotect(It.Is<string>(token => token == "invalid-token")))
.Returns(value: null);
format.Setup(mock => mock.Unprotect(It.Is<string>(token => token == "valid-token")))
.Returns(delegate
{
var identity = new ClaimsIdentity(OAuthValidationDefaults.AuthenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, "Fabrikam"));
var properties = new AuthenticationProperties();
return new AuthenticationTicket(new ClaimsPrincipal(identity),
properties, OAuthValidationDefaults.AuthenticationScheme);
});
builder.ConfigureServices(services =>
{
services.AddAuthentication();
});
builder.Configure(app =>
{
app.UseOAuthValidation(options =>
{
options.AccessTokenFormat = format.Object;
// Run the configuration delegate
// registered by the unit tests.
configuration?.Invoke(options);
});
// Add the middleware you want to test here.
app.Run(context =>
{
if (!context.User.Identities.Any(identity => identity.IsAuthenticated))
{
return context.Authentication.ChallengeAsync();
}
var identifier = context.User.FindFirst(ClaimTypes.NameIdentifier).Value;
return context.Response.WriteAsync(identifier);
});
});
return new TestServer(builder);
}