using System; using System.Security.Claims; using System.Threading.Tasks; using AMWD.Common.AspNetCore.Security.PathProtection; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; namespace UnitTests.AspNetCore.Security.PathProtection { [TestClass] [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ProtectedPathMiddlewareTests { private Mock _nextMock; private Mock _httpContextMock; private Mock _authorizationServiceMock; private Mock _authenticationServiceMock; private ProtectedPathOptions _options; [TestInitialize] public void InitializeTest() { _options = new ProtectedPathOptions { Path = "/secure/protected", PolicyName = "Protection" }; } [TestMethod] public async Task ShouldValidateAccessSuccessful() { // arrange var middleware = GetMiddleware(); var context = GetHttpContext(_options.Path); var auth = GetAuthService(true); // act await middleware.InvokeAsync(context, auth); // assert _authorizationServiceMock.Verify(s => s.AuthorizeAsync(It.IsAny(), It.IsAny(), _options.PolicyName), Times.Once); _authorizationServiceMock.VerifyNoOtherCalls(); _authenticationServiceMock.Verify(s => s.ChallengeAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); _authenticationServiceMock.VerifyNoOtherCalls(); _nextMock.Verify(n => n.Invoke(It.IsAny()), Times.Once); _nextMock.VerifyNoOtherCalls(); } [TestMethod] public async Task ShouldNotValidate() { // arrange var middleware = GetMiddleware(); var context = GetHttpContext("/some/path"); var auth = GetAuthService(true); // act await middleware.InvokeAsync(context, auth); // assert _authorizationServiceMock.Verify(s => s.AuthorizeAsync(It.IsAny(), It.IsAny(), _options.PolicyName), Times.Never); _authorizationServiceMock.VerifyNoOtherCalls(); _authenticationServiceMock.Verify(s => s.ChallengeAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); _authenticationServiceMock.VerifyNoOtherCalls(); _nextMock.Verify(n => n.Invoke(It.IsAny()), Times.Once); _nextMock.VerifyNoOtherCalls(); } [TestMethod] public async Task ShouldValidateAccessFailure() { // arrange var middleware = GetMiddleware(); var context = GetHttpContext(_options.Path); var auth = GetAuthService(false); // act await middleware.InvokeAsync(context, auth); // assert _authorizationServiceMock.Verify(s => s.AuthorizeAsync(It.IsAny(), It.IsAny(), _options.PolicyName), Times.Once); _authorizationServiceMock.VerifyNoOtherCalls(); _authenticationServiceMock.Verify(s => s.ChallengeAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); _authenticationServiceMock.VerifyNoOtherCalls(); _nextMock.Verify(n => n.Invoke(It.IsAny()), Times.Never); _nextMock.VerifyNoOtherCalls(); } private ProtectedPathMiddleware GetMiddleware() { _nextMock = new Mock(); return new ProtectedPathMiddleware(_nextMock.Object, _options); } private HttpContext GetHttpContext(string requestPath) { var requestMock = new Mock(); requestMock .Setup(r => r.Path) .Returns(new PathString(requestPath)); _authenticationServiceMock = new Mock(); var requestServicesMock = new Mock(); requestServicesMock .Setup(s => s.GetService(typeof(IAuthenticationService))) .Returns(_authenticationServiceMock.Object); _httpContextMock = new Mock(); _httpContextMock .Setup(c => c.Request) .Returns(requestMock.Object); _httpContextMock .Setup(c => c.RequestServices) .Returns(requestServicesMock.Object); return _httpContextMock.Object; } private IAuthorizationService GetAuthService(bool success) { _authorizationServiceMock = new Mock(); _authorizationServiceMock .Setup(service => service.AuthorizeAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(() => success ? AuthorizationResult.Success() : AuthorizationResult.Failed()); return _authorizationServiceMock.Object; } } }