public async Task AuthorizeAsyncEvaluatesPoliciesInPriorityOrder()
        {
            var mockActionDescriptor = new Mock <HttpActionDescriptor>();
            var mockDependencyScope  = new Mock <IDependencyScope>();
            var mockPrincipalPolicy  = new Mock <IAuthorizationPolicy>();
            var mockSslPolicy        = new Mock <IAuthorizationPolicy>();
            var httpConfiguration    = new HttpConfiguration();
            var routeData            = new HttpRouteData(new HttpRoute());
            var request = new HttpRequestMessage();
            var controllerDescriptor = new HttpControllerDescriptor {
                Configuration = httpConfiguration, ControllerName = "generic"
            };
            var controllerContext = new HttpControllerContext(httpConfiguration, routeData, request)
            {
                ControllerDescriptor = controllerDescriptor
            };
            var actionContext = new HttpActionContext(controllerContext, mockActionDescriptor.Object);

            mockActionDescriptor.SetupGet(descriptor => descriptor.ActionName).Returns("someAction");

            mockDependencyScope.Setup(scope => scope.GetServices(It.Is <Type>(param => param == typeof(IAuthorizationPolicy))))
            .Returns(new [] { mockPrincipalPolicy.Object, mockSslPolicy.Object });

            mockPrincipalPolicy.SetupGet(policy => policy.Enabled).Returns(true);
            mockPrincipalPolicy.SetupGet(policy => policy.Priority).Returns(Priority.Low);
            mockPrincipalPolicy.SetupGet(policy => policy.Policy).Returns(AuthorizationPolicy.AuthenticatedPrincipal);
            mockPrincipalPolicy.Setup(policy => policy.Evaluate(It.Is <HttpActionContext>(context => context == actionContext))).Returns(HttpStatusCode.Unauthorized);

            mockSslPolicy.SetupGet(policy => policy.Enabled).Returns(true);
            mockSslPolicy.SetupGet(policy => policy.Priority).Returns(Priority.High);
            mockSslPolicy.SetupGet(policy => policy.Policy).Returns(AuthorizationPolicy.RequireSsl);
            mockSslPolicy.Setup(policy => policy.Evaluate(It.Is <HttpActionContext>(context => context == actionContext))).Returns(HttpStatusCode.Forbidden);

            request.SetConfiguration(httpConfiguration);
            request.SetRouteData(routeData);
            request.Properties.Add(HttpPropertyKeys.DependencyScope, mockDependencyScope.Object);

            actionContext.Response = request.CreateResponse(HttpStatusCode.OK, "This was sucessful");

            var authAttribute = new OrderFulfillmentAuthorizeAttribute();

            await authAttribute.OnAuthorizationAsync(actionContext, CancellationToken.None);

            mockSslPolicy.Verify(policy => policy.Evaluate(It.IsAny <HttpActionContext>()), Times.Once, "The SSL policy should have been evaluated because it is higher priority");
            mockPrincipalPolicy.Verify(policy => policy.Evaluate(It.IsAny <HttpActionContext>()), Times.Never, "The principal  policy should not have been evaluated because it a higher priority policy already failed");
        }
        public async Task AuthorizeAsyncOverridesASuccessResultWhenNotAuthorized()
        {
            var mockActionDescriptor = new Mock <HttpActionDescriptor>();
            var mockDependencyScope  = new Mock <IDependencyScope>();
            var mockPrincipalPolicy  = new Mock <IAuthorizationPolicy>();
            var mockSslPolicy        = new Mock <IAuthorizationPolicy>();
            var httpConfiguration    = new HttpConfiguration();
            var routeData            = new HttpRouteData(new HttpRoute());
            var request = new HttpRequestMessage();
            var controllerDescriptor = new HttpControllerDescriptor {
                Configuration = httpConfiguration, ControllerName = "generic"
            };
            var controllerContext = new HttpControllerContext(httpConfiguration, routeData, request)
            {
                ControllerDescriptor = controllerDescriptor
            };
            var actionContext  = new HttpActionContext(controllerContext, mockActionDescriptor.Object);
            var expectedStatus = HttpStatusCode.Unauthorized;

            mockActionDescriptor.SetupGet(descriptor => descriptor.ActionName).Returns("someAction");

            mockDependencyScope.Setup(scope => scope.GetServices(It.Is <Type>(param => param == typeof(IAuthorizationPolicy))))
            .Returns(new [] { mockPrincipalPolicy.Object, mockSslPolicy.Object });

            mockPrincipalPolicy.SetupGet(policy => policy.Enabled).Returns(true);
            mockPrincipalPolicy.SetupGet(policy => policy.Policy).Returns(AuthorizationPolicy.AuthenticatedPrincipal);
            mockPrincipalPolicy.Setup(policy => policy.Evaluate(It.Is <HttpActionContext>(context => context == actionContext))).Returns(expectedStatus);

            mockSslPolicy.SetupGet(policy => policy.Enabled).Returns(true);
            mockSslPolicy.SetupGet(policy => policy.Policy).Returns(AuthorizationPolicy.RequireSsl);
            mockSslPolicy.Setup(policy => policy.Evaluate(It.Is <HttpActionContext>(context => context == actionContext))).Returns((HttpStatusCode?)null);

            request.SetConfiguration(httpConfiguration);
            request.SetRouteData(routeData);
            request.Properties.Add(HttpPropertyKeys.DependencyScope, mockDependencyScope.Object);

            actionContext.Response = request.CreateResponse(HttpStatusCode.OK, "This was sucessful");

            var authAttribute = new OrderFulfillmentAuthorizeAttribute();

            await authAttribute.OnAuthorizationAsync(actionContext, CancellationToken.None);

            actionContext.Response.Should().NotBeNull("because a failed authorization should set the result");
            actionContext.Response.StatusCode.Should().Be(expectedStatus, "because callers are forbidden when authorization fails.");
        }
        public async Task AuthorizeAsyncRespectsAFailedRequest()
        {
            var mockActionDescriptor = new Mock <HttpActionDescriptor>();
            var mockDependencyScope  = new Mock <IDependencyScope>();
            var mockAuthPolicy       = new Mock <IAuthorizationPolicy>();
            var httpConfiguration    = new HttpConfiguration();
            var routeData            = new HttpRouteData(new HttpRoute());
            var request = new HttpRequestMessage();
            var controllerDescriptor = new HttpControllerDescriptor {
                Configuration = httpConfiguration, ControllerName = "generic"
            };
            var controllerContext = new HttpControllerContext(httpConfiguration, routeData, request)
            {
                ControllerDescriptor = controllerDescriptor
            };
            var actionContext = new HttpActionContext(controllerContext, mockActionDescriptor.Object);
            var response      = request.CreateResponse(HttpStatusCode.ServiceUnavailable);

            mockActionDescriptor.SetupGet(descriptor => descriptor.ActionName).Returns("someAction");

            mockDependencyScope.Setup(scope => scope.GetServices(It.Is <Type>(param => param == typeof(IAuthorizationPolicy))))
            .Returns(new [] { mockAuthPolicy.Object });

            mockAuthPolicy.SetupGet(policy => policy.Enabled).Returns(true);
            mockAuthPolicy.SetupGet(policy => policy.Policy).Returns(AuthorizationPolicy.AuthenticatedPrincipal);
            mockAuthPolicy.Setup(policy => policy.Evaluate(It.Is <HttpActionContext>(context => context == actionContext))).Returns(HttpStatusCode.Unauthorized);

            request.SetConfiguration(httpConfiguration);
            request.SetRouteData(routeData);
            request.Properties.Add(HttpPropertyKeys.DependencyScope, mockDependencyScope.Object);

            actionContext.Response = response;

            var authAttribute = new OrderFulfillmentAuthorizeAttribute(AuthorizationPolicy.AuthenticatedPrincipal);

            await authAttribute.OnAuthorizationAsync(actionContext, CancellationToken.None);

            actionContext.Response.Should().Be(response, "because the existing failure result should have been detected before authorization took place");

            mockDependencyScope.Verify(scope => scope.GetServices(It.Is <Type>(param => param == typeof(IAuthorizationPolicy))), Times.Never, "The cancellation should have taken place before a policy was sought");
        }
        public async Task AuthorizeAsyncDoesNotFailWhenPoliciesAreSatisfied()
        {
            var mockActionDescriptor = new Mock <HttpActionDescriptor>();
            var mockDependencyScope  = new Mock <IDependencyScope>();
            var mockPrincipalPolicy  = new Mock <IAuthorizationPolicy>();
            var mockSslPolicy        = new Mock <IAuthorizationPolicy>();
            var httpConfiguration    = new HttpConfiguration();
            var routeData            = new HttpRouteData(new HttpRoute());
            var request = new HttpRequestMessage();
            var controllerDescriptor = new HttpControllerDescriptor {
                Configuration = httpConfiguration, ControllerName = "generic"
            };
            var controllerContext = new HttpControllerContext(httpConfiguration, routeData, request)
            {
                ControllerDescriptor = controllerDescriptor
            };
            var actionContext = new HttpActionContext(controllerContext, mockActionDescriptor.Object);

            mockActionDescriptor.SetupGet(descriptor => descriptor.ActionName).Returns("someAction");

            mockDependencyScope.Setup(scope => scope.GetServices(It.Is <Type>(param => param == typeof(IAuthorizationPolicy))))
            .Returns(new [] { mockPrincipalPolicy.Object, mockSslPolicy.Object });

            mockPrincipalPolicy.SetupGet(policy => policy.Enabled).Returns(true);
            mockPrincipalPolicy.SetupGet(policy => policy.Policy).Returns(AuthorizationPolicy.AuthenticatedPrincipal);
            mockPrincipalPolicy.Setup(policy => policy.Evaluate(It.Is <HttpActionContext>(context => context == actionContext))).Returns((HttpStatusCode?)null);

            mockSslPolicy.SetupGet(policy => policy.Enabled).Returns(true);
            mockSslPolicy.SetupGet(policy => policy.Policy).Returns(AuthorizationPolicy.RequireSsl);
            mockSslPolicy.Setup(policy => policy.Evaluate(It.Is <HttpActionContext>(context => context == actionContext))).Returns((HttpStatusCode?)null);

            request.SetConfiguration(httpConfiguration);
            request.SetRouteData(routeData);
            request.Properties.Add(HttpPropertyKeys.DependencyScope, mockDependencyScope.Object);

            var authAttribute = new OrderFulfillmentAuthorizeAttribute();

            await authAttribute.OnAuthorizationAsync(actionContext, CancellationToken.None);

            actionContext.Response.Should().BeNull("because a result should only be set on failure");
        }