/
githubmirror
/
aspnetcore
Обзор
Документация
Войти
/
githubmirror
/
aspnetcore
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Servers/HttpSys/test/FunctionalTests/AuthenticationTests.cs
466 строк
21 KB
Evgeny Kotkov
http.sys: Allow configuring HTTP_AUTH_EX_FLAGs as options (#51833)
09 фев 2024, 11:36
Не верифицирован
09 фев 2024, 11:36
4deb60b
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Linq; using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.InternalTesting; using Xunit; namespace Microsoft.AspNetCore.Server.HttpSys; public class AuthenticationTests : LoggedTest { private static bool AllowAnoymous = true; private static bool DenyAnoymous = false; [ConditionalTheory] [InlineData(AuthenticationSchemes.None)] [InlineData(AuthenticationSchemes.Negotiate)] [InlineData(AuthenticationSchemes.NTLM)] // [InlineData(AuthenticationSchemes.Digest)] [InlineData(AuthenticationSchemes.Basic)] [InlineData(AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM | /*AuthenticationSchemes.Digest |*/ AuthenticationSchemes.Basic)] public async Task AuthTypes_AllowAnonymous_NoChallenge(AuthenticationSchemes authType) { using (var server = Utilities.CreateDynamicHost(authType, AllowAnoymous, out var address, httpContext => { Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); Assert.False(httpContext.User.Identity.IsAuthenticated); return Task.FromResult(0); }, LoggerFactory)) { var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Empty(response.Headers.WwwAuthenticate); } } [ConditionalTheory] [InlineData(AuthenticationSchemes.Negotiate)] [InlineData(AuthenticationSchemes.NTLM)] // [InlineData(AuthenticationSchemes.Digest)] // TODO: Not implemented [InlineData(AuthenticationSchemes.Basic)] public async Task AuthType_RequireAuth_ChallengesAdded(AuthenticationSchemes authType) { using (var server = Utilities.CreateDynamicHost(authType, DenyAnoymous, out var address, httpContext => { throw new NotImplementedException(); }, LoggerFactory)) { var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal(authType.ToString(), response.Headers.WwwAuthenticate.ToString(), StringComparer.OrdinalIgnoreCase); } } [ConditionalTheory] [InlineData(AuthenticationSchemes.Negotiate)] [InlineData(AuthenticationSchemes.NTLM)] // [InlineData(AuthenticationSchemes.Digest)] // TODO: Not implemented [InlineData(AuthenticationSchemes.Basic)] public async Task AuthType_AllowAnonymousButSpecify401_ChallengesAdded(AuthenticationSchemes authType) { using (var server = Utilities.CreateDynamicHost(authType, AllowAnoymous, out var address, httpContext => { Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); Assert.False(httpContext.User.Identity.IsAuthenticated); httpContext.Response.StatusCode = 401; return Task.FromResult(0); }, LoggerFactory)) { var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal(authType.ToString(), response.Headers.WwwAuthenticate.ToString(), StringComparer.OrdinalIgnoreCase); } } [ConditionalFact] public async Task MultipleAuthTypes_AllowAnonymousButSpecify401_ChallengesAdded() { string address; using (Utilities.CreateHttpAuthServer( AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM /* | AuthenticationSchemes.Digest TODO: Not implemented */ | AuthenticationSchemes.Basic, true, out address, httpContext => { Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); Assert.False(httpContext.User.Identity.IsAuthenticated); httpContext.Response.StatusCode = 401; return Task.FromResult(0); }, LoggerFactory)) { var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal("Negotiate, NTLM, basic", response.Headers.WwwAuthenticate.ToString(), StringComparer.OrdinalIgnoreCase); } } [ConditionalTheory] [InlineData(AuthenticationSchemes.Negotiate)] [InlineData(AuthenticationSchemes.NTLM)] // [InlineData(AuthenticationSchemes.Digest)] // TODO: Not implemented // [InlineData(AuthenticationSchemes.Basic)] // Doesn't work with default creds [InlineData(AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM | /* AuthenticationSchemes.Digest |*/ AuthenticationSchemes.Basic)] public async Task AuthTypes_AllowAnonymousButSpecify401_Success(AuthenticationSchemes authType) { int requestId = 0; using (var server = Utilities.CreateDynamicHost(authType, AllowAnoymous, out var address, httpContext => { Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); if (requestId == 0) { Assert.False(httpContext.User.Identity.IsAuthenticated); httpContext.Response.StatusCode = 401; } else if (requestId == 1) { Assert.True(httpContext.User.Identity.IsAuthenticated); } else { throw new NotImplementedException(); } requestId++; return Task.FromResult(0); }, LoggerFactory)) { var response = await SendRequestAsync(address, useDefaultCredentials: true); Assert.Equal(HttpStatusCode.OK, response.StatusCode); } } [ConditionalTheory] [InlineData(AuthenticationSchemes.Negotiate)] [InlineData(AuthenticationSchemes.NTLM)] // [InlineData(AuthenticationSchemes.Digest)] // TODO: Not implemented // [InlineData(AuthenticationSchemes.Basic)] // Doesn't work with default creds [InlineData(AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM | /* AuthenticationSchemes.Digest |*/ AuthenticationSchemes.Basic)] public async Task AuthTypes_RequireAuth_Success(AuthenticationSchemes authType) { using (var server = Utilities.CreateDynamicHost(authType, DenyAnoymous, out var address, httpContext => { Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); Assert.True(httpContext.User.Identity.IsAuthenticated); return Task.FromResult(0); }, LoggerFactory)) { var response = await SendRequestAsync(address, useDefaultCredentials: true); Assert.Equal(HttpStatusCode.OK, response.StatusCode); } } // https://github.com/aspnet/Logging/issues/543#issuecomment-321907828 [ConditionalFact] public async Task AuthTypes_AccessUserInOnCompleted_Success() { var completed = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); string userName = null; var authTypes = AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM; using (var server = Utilities.CreateDynamicHost(authTypes, DenyAnoymous, out var address, httpContext => { Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); Assert.True(httpContext.User.Identity.IsAuthenticated); httpContext.Response.OnCompleted(() => { userName = httpContext.User.Identity.Name; completed.SetResult(); return Task.CompletedTask; }); return Task.FromResult(0); }, LoggerFactory)) { var response = await SendRequestAsync(address, useDefaultCredentials: true); Assert.Equal(HttpStatusCode.OK, response.StatusCode); await completed.Task.TimeoutAfter(TimeSpan.FromSeconds(5)); Assert.False(string.IsNullOrEmpty(userName)); } } [ConditionalTheory] [InlineData(AuthenticationSchemes.Negotiate)] [InlineData(AuthenticationSchemes.NTLM)] // [InlineData(AuthenticationSchemes.Digest)] [InlineData(AuthenticationSchemes.Basic)] [InlineData(AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM | /*AuthenticationSchemes.Digest |*/ AuthenticationSchemes.Basic)] public async Task AuthTypes_AuthenticateWithNoUser_NoResults(AuthenticationSchemes authType) { var authTypeList = authType.ToString().Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); using (var server = Utilities.CreateDynamicHost(authType, AllowAnoymous, out var address, async httpContext => { Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); Assert.False(httpContext.User.Identity.IsAuthenticated); var authResults = await httpContext.AuthenticateAsync(HttpSysDefaults.AuthenticationScheme); Assert.False(authResults.Succeeded); Assert.True(authResults.None); }, LoggerFactory)) { var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Empty(response.Headers.WwwAuthenticate); } } [ConditionalTheory] [InlineData(AuthenticationSchemes.Negotiate)] [InlineData(AuthenticationSchemes.NTLM)] // [InlineData(AuthenticationSchemes.Digest)] // [InlineData(AuthenticationSchemes.Basic)] // Doesn't work with default creds [InlineData(AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM | /*AuthenticationSchemes.Digest |*/ AuthenticationSchemes.Basic)] public async Task AuthTypes_AuthenticateWithUser_OneResult(AuthenticationSchemes authType) { using (var server = Utilities.CreateDynamicHost(authType, DenyAnoymous, out var address, async httpContext => { Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); Assert.True(httpContext.User.Identity.IsAuthenticated); var authResults = await httpContext.AuthenticateAsync(HttpSysDefaults.AuthenticationScheme); Assert.True(authResults.Succeeded); }, LoggerFactory)) { var response = await SendRequestAsync(address, useDefaultCredentials: true); Assert.Equal(HttpStatusCode.OK, response.StatusCode); } } [ConditionalTheory] [InlineData(AuthenticationSchemes.Negotiate)] [InlineData(AuthenticationSchemes.NTLM)] // [InlineData(AuthenticationSchemes.Digest)] [InlineData(AuthenticationSchemes.Basic)] [InlineData(AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM | /*AuthenticationSchemes.Digest |*/ AuthenticationSchemes.Basic)] public async Task AuthTypes_ChallengeWithoutAuthTypes_AllChallengesSent(AuthenticationSchemes authType) { var authTypeList = authType.ToString().Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); using (var server = Utilities.CreateDynamicHost(authType, AllowAnoymous, out var address, httpContext => { Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); Assert.False(httpContext.User.Identity.IsAuthenticated); return httpContext.ChallengeAsync(HttpSysDefaults.AuthenticationScheme); }, LoggerFactory)) { var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal(authTypeList.Count(), response.Headers.WwwAuthenticate.Count); } } [ConditionalTheory] [InlineData(AuthenticationSchemes.Negotiate)] [InlineData(AuthenticationSchemes.NTLM)] // [InlineData(AuthenticationSchemes.Digest)] [InlineData(AuthenticationSchemes.Basic)] [InlineData(AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM | /*AuthenticationSchemes.Digest |*/ AuthenticationSchemes.Basic)] public async Task AuthTypes_ChallengeWithAllAuthTypes_AllChallengesSent(AuthenticationSchemes authType) { var authTypeList = authType.ToString().Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); using (var server = Utilities.CreateDynamicHost(authType, AllowAnoymous, out var address, async httpContext => { Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); Assert.False(httpContext.User.Identity.IsAuthenticated); await httpContext.ChallengeAsync(HttpSysDefaults.AuthenticationScheme); }, LoggerFactory)) { var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal(authTypeList.Count(), response.Headers.WwwAuthenticate.Count); } } [ConditionalFact] public async Task AuthTypes_OneChallengeSent() { var authTypes = AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM | /*AuthenticationSchemes.Digest |*/ AuthenticationSchemes.Basic; using (var server = Utilities.CreateDynamicHost(authTypes, AllowAnoymous, out var address, httpContext => { Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); Assert.False(httpContext.User.Identity.IsAuthenticated); return httpContext.ChallengeAsync(HttpSysDefaults.AuthenticationScheme); }, LoggerFactory)) { var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal(3, response.Headers.WwwAuthenticate.Count); } } [ConditionalTheory] [InlineData(AuthenticationSchemes.Negotiate)] [InlineData(AuthenticationSchemes.NTLM)] // [InlineData(AuthenticationSchemes.Digest)] [InlineData(AuthenticationSchemes.Basic)] [InlineData(AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM | /*AuthenticationSchemes.Digest |*/ AuthenticationSchemes.Basic)] [InlineData(AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM)] [InlineData(AuthenticationSchemes.Negotiate | AuthenticationSchemes.Basic)] [InlineData(AuthenticationSchemes.NTLM | AuthenticationSchemes.Basic)] public async Task AuthTypes_ChallengeWillAskForAllEnabledSchemes(AuthenticationSchemes authType) { var authTypeList = authType.ToString().Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); using (var server = Utilities.CreateDynamicHost(authType, AllowAnoymous, out var address, httpContext => { Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); Assert.False(httpContext.User.Identity.IsAuthenticated); return httpContext.ChallengeAsync(HttpSysDefaults.AuthenticationScheme); }, LoggerFactory)) { var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal(authTypeList.Count(), response.Headers.WwwAuthenticate.Count); } } [ConditionalFact] public async Task AuthTypes_Forbid_Forbidden() { var authTypes = AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM | /*AuthenticationSchemes.Digest |*/ AuthenticationSchemes.Basic; using (var server = Utilities.CreateDynamicHost(authTypes, AllowAnoymous, out var address, httpContext => { Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); Assert.False(httpContext.User.Identity.IsAuthenticated); return httpContext.ForbidAsync(HttpSysDefaults.AuthenticationScheme); }, LoggerFactory)) { var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); Assert.Empty(response.Headers.WwwAuthenticate); } } [ConditionalTheory] [InlineData(AuthenticationSchemes.Negotiate)] [InlineData(AuthenticationSchemes.NTLM)] // [InlineData(AuthenticationSchemes.Digest)] // Not implemented // [InlineData(AuthenticationSchemes.Basic)] // Can't log in with UseDefaultCredentials public async Task AuthTypes_UnathorizedAuthenticatedAuthType_Unauthorized(AuthenticationSchemes authType) { using (var server = Utilities.CreateDynamicHost(authType, DenyAnoymous, out var address, httpContext => { Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); Assert.True(httpContext.User.Identity.IsAuthenticated); return httpContext.ChallengeAsync(HttpSysDefaults.AuthenticationScheme, null); }, LoggerFactory)) { var response = await SendRequestAsync(address, useDefaultCredentials: true); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Single(response.Headers.WwwAuthenticate); Assert.Equal(authType.ToString(), response.Headers.WwwAuthenticate.First().Scheme); } } [ConditionalTheory] [InlineData(AuthenticationSchemes.Negotiate)] [InlineData(AuthenticationSchemes.NTLM)] // [InlineData(AuthenticationSchemes.Digest)] // TODO: Not implemented // [InlineData(AuthenticationSchemes.Basic)] // Doesn't work with default creds [InlineData(AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM | /* AuthenticationSchemes.Digest |*/ AuthenticationSchemes.Basic)] public async Task AuthTypes_DisableAutomaticAuthentication(AuthenticationSchemes authType) { using (var server = Utilities.CreateDynamicHost(out var address, options => { options.Authentication.AutomaticAuthentication = false; options.Authentication.Schemes = authType; options.Authentication.AllowAnonymous = DenyAnoymous; }, async httpContext => { Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); Assert.False(httpContext.User.Identity.IsAuthenticated); var authenticateResult = await httpContext.AuthenticateAsync(HttpSysDefaults.AuthenticationScheme); Assert.NotNull(authenticateResult.Principal); Assert.NotNull(authenticateResult.Principal.Identity); Assert.True(authenticateResult.Principal.Identity.IsAuthenticated); }, LoggerFactory)) { var response = await SendRequestAsync(address, useDefaultCredentials: true); Assert.Equal(HttpStatusCode.OK, response.StatusCode); } } [ConditionalTheory] [InlineData(AuthenticationSchemes.Negotiate)] [InlineData(AuthenticationSchemes.NTLM)] [InlineData(AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM)] public async Task AuthTypes_EnableKerberosCredentialCaching(AuthenticationSchemes authType) { using (var server = Utilities.CreateDynamicHost(out var address, options => { options.Authentication.Schemes = authType; options.Authentication.AllowAnonymous = DenyAnoymous; options.Authentication.EnableKerberosCredentialCaching = true; }, httpContext => { // There doesn't seem to be a simple way of testing the `EnableKerberosCredentialCaching` // setting, but at least check that the server works. Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); Assert.True(httpContext.User.Identity.IsAuthenticated); return Task.FromResult(0); }, LoggerFactory)) { var response = await SendRequestAsync(address, useDefaultCredentials: true); Assert.Equal(HttpStatusCode.OK, response.StatusCode); } } [ConditionalTheory] [InlineData(AuthenticationSchemes.Negotiate)] [InlineData(AuthenticationSchemes.NTLM)] [InlineData(AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM)] public async Task AuthTypes_CaptureCredentials(AuthenticationSchemes authType) { using (var server = Utilities.CreateDynamicHost(out var address, options => { options.Authentication.Schemes = authType; options.Authentication.AllowAnonymous = DenyAnoymous; options.Authentication.CaptureCredentials = true; }, httpContext => { // There doesn't seem to be a simple way of testing the `CaptureCredentials` // setting, but at least check that the server works. Assert.NotNull(httpContext.User); Assert.NotNull(httpContext.User.Identity); Assert.True(httpContext.User.Identity.IsAuthenticated); return Task.FromResult(0); }, LoggerFactory)) { var response = await SendRequestAsync(address, useDefaultCredentials: true); Assert.Equal(HttpStatusCode.OK, response.StatusCode); } } private async Task<HttpResponseMessage> SendRequestAsync(string uri, bool useDefaultCredentials = false) { HttpClientHandler handler = new HttpClientHandler(); handler.UseDefaultCredentials = useDefaultCredentials; using (HttpClient client = new HttpClient(handler)) { return await client.GetAsync(uri); } } }