public void RequiresAuthenticationAttribute_Authorize_Allowed_Authenticated_User()
 {
     RequiresAuthenticationAttribute attr = new RequiresAuthenticationAttribute();
     using (AuthorizationContext context = new AuthorizationContext(/*instance*/ null, "testOp", "testOpType", /*IServiceProvider*/ null, /*items*/ null))
     {
         AuthorizationResult result = attr.Authorize(this.CreateIPrincipal("name"), context);
         Assert.AreSame(result, AuthorizationResult.Allowed, "Expected authorization to be allowed on new principal");
     }
 }
 /// <summary>
 /// Determines whether the given <paramref name="principal"/> is authorized to perform a specific operation
 /// described by the given <paramref name="authorizationContext"/>.
 /// </summary>
 /// <remarks>This method is the concrete entry point for authorization.  It delegates to the derived class's
 /// <see cref="IsAuthorized"/> method for implementation-specific authorization.
 /// </remarks>
 /// <param name="principal">The <see cref="IPrincipal"/> to be authorized.</param>
 /// <param name="authorizationContext">The <see cref="AuthorizationContext"/> describing the context in which
 /// authorization has been requested.</param>
 /// <returns>An <see cref="AuthorizationResult"/> that indicates whether the operation is allowed or denied.
 /// A return of <see cref="AuthorizationResult.Allowed"/> indicates the operation is allowed.
 /// A return of any other (non-null) <see cref="AuthorizationResult"/> indicates the request has been denied.
 /// The user visible error message for the denial is found in <see cref="AuthorizationResult.ErrorMessage"/>.
 /// </returns>
 public AuthorizationResult Authorize(IPrincipal principal, AuthorizationContext authorizationContext)
 {
     if (principal == null)
     {
         throw new ArgumentNullException("principal");
     }
     if (authorizationContext == null)
     {
         throw new ArgumentNullException("authorizationContext");
     }
     return this.IsAuthorized(principal, authorizationContext);
 }
        public void RequiresAuthenticationAttribute_Authorize_Denied_Anonymous_User()
        {
            RequiresAuthenticationAttribute attr = new RequiresAuthenticationAttribute();
            using (AuthorizationContext context = new AuthorizationContext(/*instance*/ null, "testOp", "testOpType", /*IServiceProvider*/ null, /*items*/ null))
            {
                AuthorizationResult result = attr.Authorize(new GenericPrincipal(WindowsIdentity.GetAnonymous(), null), context);
                Assert.AreNotSame(result, AuthorizationResult.Allowed, "Expected denied result for anon user");

                string expectedMessage = String.Format(CultureInfo.CurrentCulture, Resource.AuthorizationAttribute_Default_Message, context.Operation);
                Assert.AreEqual(expectedMessage, result.ErrorMessage, "Expected to see default denial error message");
            }
        }
        public void AuthorizationContext_Ctor_Template_With_ServiceProvider()
        {
            IServiceProvider provider = new AuthorizationContextServiceProvider();
            using (AuthorizationContext context = new AuthorizationContext(provider))
            {

                // GetService should delegate to supplied provider
                string mockStringService = context.GetService(typeof(string)) as string;
                Assert.AreEqual("mockStringService", mockStringService, "Expected GetService to delegate to mock provider");

                // Shared validation logic for templates and container
                this.Validate_AuthorizationContext_Template(context);
                this.Validate_AuthorizationContext_ServiceContainer(context);
            }
        }
        public void AuthorizationContext_Ctor_Template_No_ServiceProvider()
        {
            // Null is allowed for IServiceProvider
            using (AuthorizationContext context = new AuthorizationContext(null))
            {

                // Random GetService request does not throw and returns null
                object service = context.GetService(typeof(string));
                Assert.IsNull(service, "Expected GetService to return null");

                // Shared validation logic for templates and container
                this.Validate_AuthorizationContext_Template(context);
                this.Validate_AuthorizationContext_ServiceContainer(context);
            }
        }
        public void RequiresRoleAttribute_NoRolesDefined_Throws()
        {
            // Validate that we can access all forms of the Roles property without an exception
            var ignored = new RequiresRoleAttribute().Roles;
            ignored = new RequiresRoleAttribute((string)null).Roles;
            ignored = new RequiresRoleAttribute((string[])null).Roles;

            // But attempting do authorization with null roles throws
            using (AuthorizationContext context = new AuthorizationContext(/*instance*/ null, "testOp", "testOpType", /*IServiceProvider*/ null, /*items*/ null))
            {
                ExceptionHelper.ExpectInvalidOperationException(
                    () => { new RequiresRoleAttribute((string[])null).Authorize(this.CreateIPrincipal("John Doe"), context); },
                    Resource.RequiresRoleAttribute_MustSpecifyRole);
            }
        }
        public void AuthorizationContext_Ctor_And_Properties()
        {
            // Operation param cannot be null or empty
            ExceptionHelper.ExpectArgumentNullExceptionStandard(() => new AuthorizationContext(/*instance*/ null, /*operation*/ null, "operationType", /*serviceProvider*/ null, items: null), "operation");
            ExceptionHelper.ExpectArgumentNullExceptionStandard(() => new AuthorizationContext(/*instance*/ null, /*operation*/ string.Empty, "operationType", /*serviceProvider*/ null, items: null), "operation");

            // Operation param cannot be null or empty
            ExceptionHelper.ExpectArgumentNullExceptionStandard(() => new AuthorizationContext(/*instance*/ null, "operation", /*operationType*/ null, /*serviceProvider*/ null, items: null), "operationType");
            ExceptionHelper.ExpectArgumentNullExceptionStandard(() => new AuthorizationContext(/*instance*/ null, "operation", /*operationType*/ string.Empty, /*serviceProvider*/ null, items: null), "operationType");

            string instance = "mockEntity";   // type is only required to be object
            string operation = "testOp";
            string operationType = "Query";
            IServiceProvider serviceProvider = new AuthorizationContextServiceProvider();
            Dictionary<object, object> items = new Dictionary<object, object>();
            items["mockItem"] = "mockValue";

            // Fully formed valid ctor
            using (AuthorizationContext context = new AuthorizationContext(instance, operation, operationType, serviceProvider, items))
            {

                // Instance and Operation should be what the ctor set
                Assert.AreEqual(instance, context.Instance, "AuthorizationContext.Instance property failure");
                Assert.AreEqual(operation, context.Operation, "AuthorizationContext.Operation property failure");
                Assert.AreEqual(operationType, context.OperationType, "AuthorizationContext.Operation property failure");

                // The service provider gets wrapped, so verify we can ask for a service it knew how to provide
                string mockStringService = (string)context.GetService(typeof(string));
                Assert.AreEqual("mockStringService", mockStringService, "AuthorizationContext.GetService() failed to respect input service provider");

                // The items param should have been cloned, so verify it has the same content
                Assert.IsNotNull(context.Items, "AuthorizationContext.Items property failure");
                Assert.IsTrue(context.Items.ContainsKey("mockItem"), "AuthorizationContext.Items failed to clone input items");
                Assert.AreEqual("mockValue", context.Items["mockItem"], "AuthorizationContext.Items failed to set initial value correctly");

                // Add item to original.  The snapshot in the context should be unaffected.
                items["mockItem2"] = "mockValue2";
                Assert.IsFalse(context.Items.ContainsKey("mockItem2"), "AuthorizationContext items should have copied snapshot input Items");

                // Add an item to the context's Items to verify it is mutable
                context.Items["mockItem3"] = "mockValue3";
                Assert.IsTrue(context.Items.ContainsKey("mockItem3") && (string)context.Items["mockItem3"] == "mockValue3", "Could not modify AuthorizationContext.Items");

                // Share logic to validate ServiceContainer
                this.Validate_AuthorizationContext_ServiceContainer(context);
            }
        }
        protected override AuthorizationResult IsAuthorized(IPrincipal principal, AuthorizationContext authorizationContext)
        {
            // Allowed only on domain operations for entities with a StateName property
            PropertyInfo property = authorizationContext.Instance == null ? null : authorizationContext.Instance.GetType().GetProperty("StateName");
            string stateName = property == null ? null : property.GetValue(authorizationContext.Instance, null) as string;
            if (stateName == null)
            {
                throw new InvalidOperationException("The RequiresUserForStateAttribute can be used only on entities with a StateName property");
            }

            // If not the city, it is allowed
            if (!string.Equals(this._stateName, stateName, StringComparison.OrdinalIgnoreCase))
            {
                return AuthorizationResult.Allowed;
            }

            // It is the city.  Let base class continue the authorization
            return base.IsAuthorized(principal, authorizationContext);
        }
        public void RequiresRoleAttribute_Authorize_SingleAttribute()
        {
            IPrincipal user1 = this.CreateIPrincipal("user1", "role1");
            IPrincipal user2 = this.CreateIPrincipal("user1", "role2");
            RequiresRoleAttribute requireRole1 = new RequiresRoleAttribute("role1");
            using (AuthorizationContext context = new AuthorizationContext(/*instance*/ null, "testOp", "testOpType", /*IServiceProvider*/ null, /*items*/ null))
            {

                // user in role1 should be allowed
                AuthorizationResult result = requireRole1.Authorize(user1, context);
                Assert.AreSame(AuthorizationResult.Allowed, result, "Expected user in role1 to be authorized when only role1 is permitted");

                // user in role2 should be denied
                result = requireRole1.Authorize(user2, context);
                Assert.AreNotSame(AuthorizationResult.Allowed, result, "Expected user in role2 to be denied when only role1 is permitted");

                // Denial error message should reflect default plus operation
                string expectedMessage = String.Format(CultureInfo.CurrentCulture, Resource.AuthorizationAttribute_Default_Message, context.Operation);
                Assert.AreEqual(expectedMessage, result.ErrorMessage, "Expected to see default denial error message");

                // user in role1 should be allowed if role1 + role2 + role3 are permitted
                RequiresRoleAttribute requireRole123 = new RequiresRoleAttribute(new string[] { "role1", "role2", "role3" });
                result = requireRole123.Authorize(user1, context);
                Assert.AreSame(AuthorizationResult.Allowed, result, "Expected user1 in role1 to be authorized when role1, role2, and role3 are all permitted");

                // user is in multiple roles (1, 2, and 3) should be allowed if any of these 3 roles are allowed
                IPrincipal user13 = this.CreateIPrincipal("user1", "role1", "role3");
                result = requireRole123.Authorize(user13, context);
                Assert.AreSame(AuthorizationResult.Allowed, result, "Expected user1 in role1 and role3 to be authorized when role1, role2, and role3 are all permitted");

                // user is in none of the required roles
                RequiresRoleAttribute requireRole567 = new RequiresRoleAttribute(new string[] { "role5", "role6", "role7" });
                result = requireRole567.Authorize(user1, context);
                Assert.AreNotSame(AuthorizationResult.Allowed, result, "Expected user in role1 to be denied when only roles 5, 6, and 7 are allowed");
            }
        }
        /// <summary>
        /// Determines whether the given <paramref name="principal"/> is authorized to perform the operation
        /// specified by given <paramref name="authorizationContext"/>.
        /// </summary>
        /// <remarks>This method returns <see cref="AuthorizationResult.Allowed"/> only when the <paramref name="principal"/>
        /// is authenticated and belongs to at least one of the roles specified in <see cref="Roles"/>.
        /// <para>
        /// To require the principal to belong to multiple roles, multiple <see cref="RequiresRoleAttribute"/>
        /// custom attributes should be used on the respective operation.
        /// </para>
        /// </remarks>
        /// <param name="principal">The <see cref="IPrincipal"/> to authorize.</param>
        /// <param name="authorizationContext">The <see cref="AuthorizationContext"/> in which authorization is required.</param>
        /// <returns>A <see cref="AuthorizationResult"/> indicating whether or not the <paramref name="principal"/> is authorized.
        /// The value <see cref="AuthorizationResult.Allowed"/> indicates authorization is granted.  Any other value
        /// indicates it has been denied.</returns>
        protected override AuthorizationResult IsAuthorized(IPrincipal principal, AuthorizationContext authorizationContext)
        {
            if (this._roles.Count == 0)
            {
                throw new InvalidOperationException(Resource.RequiresRoleAttribute_MustSpecifyRole);
            }

            if (principal.Identity != null && principal.Identity.IsAuthenticated)
            {
                // the user has to be in at least one of the roles
                foreach (string role in this._roles)
                {
                    if (principal.IsInRole(role))
                    {
                        return AuthorizationResult.Allowed;
                    }
                }
            }

            return new AuthorizationResult(this.FormatErrorMessage(authorizationContext.Operation));
        }
        // Helper method to validate all forms of AuthorizationContext honor ServiceContainer
        public void Validate_AuthorizationContext_ServiceContainer(AuthorizationContext context)
        {
            // Asking for a ServiceContainer creates one
            IServiceContainer container = context.GetService(typeof(IServiceContainer)) as IServiceContainer;
            Assert.IsNotNull(container, "Expected lazily created ServiceContainer");

            // The ServiceContainer should work.  Add a service, test it, and remove it
            Guid guid = Guid.NewGuid();
            container.AddService(typeof(Guid), guid);
            object service = container.GetService(typeof(Guid));
            Assert.AreEqual(guid, service, "ServiceContainer did not honor addService");

            container.RemoveService(typeof(Guid));
            service = container.GetService(typeof(Guid));
            Assert.IsNull(service, "ServiceContainer did not honor removeService");
        }
 protected override AuthorizationResult IsAuthorized(IPrincipal principal, AuthorizationContext authorizationContext)
 {
     return (principal.Identity != null && principal.Identity.IsAuthenticated && string.Equals(this._userName, principal.Identity.Name, StringComparison.InvariantCultureIgnoreCase))
                 ? AuthorizationResult.Allowed
                 : new AuthorizationResult(this.FormatErrorMessage(authorizationContext.Operation));
 }
 /// <summary>
  /// Determines whether the given <paramref name="principal"/> is authorized to perform the operation
  /// specified by given <paramref name="authorizationContext"/>.
  /// </summary>
  /// <remarks>
  /// This method returns <see cref="AuthorizationResult.Allowed"/> only when the <paramref name="principal"/>
  /// is authenticated.
  /// </remarks>
  /// <param name="principal">The <see cref="IPrincipal"/> to authorize.</param>
  /// <param name="authorizationContext">The <see cref="AuthorizationContext"/> in which authorization is required.</param>
  /// <returns>A <see cref="AuthorizationResult"/> indicating whether or not the <paramref name="principal"/> is authorized.
  /// The value <see cref="AuthorizationResult.Allowed"/> indicates authorization is granted.  Any other value
  /// indicates it has been denied.</returns>        
  protected override AuthorizationResult IsAuthorized(IPrincipal principal, AuthorizationContext authorizationContext)
  {
      return (principal.Identity != null && principal.Identity.IsAuthenticated)
                  ? AuthorizationResult.Allowed
                  : new AuthorizationResult(this.FormatErrorMessage(authorizationContext.Operation));
  }
 /// <summary>
 /// Implementation specific method to determine whether the given <paramref name="principal"/>
 /// is authorized to perform a specific operation described by 
 /// the given <paramref name="authorizationContext"/>.
 /// </summary>
 /// <remarks>This protected abstract method contains the implementation-specific logic for this particular
 /// subclass of <see cref="AuthorizationAttribute"/>.  It is invoked strictly by the public <see cref="Authorize"/> method.
 /// </remarks>
 /// <param name="principal">The <see cref="IPrincipal"/> to be authorized.</param>
 /// <param name="authorizationContext">The <see cref="AuthorizationContext"/> describing the context in which
 /// authorization has been requested.</param>
 /// <returns>An <see cref="AuthorizationResult"/> that indicates whether the operation is allowed or denied.
 /// A return of <see cref="AuthorizationResult.Allowed"/> indicates the operation is allowed.
 /// A return of any other non-null <see cref="AuthorizationResult"/> indicates the request has been denied.
 /// The user visible error message for the denial is found in <see cref="AuthorizationResult.ErrorMessage"/>
 /// </returns>
 protected abstract AuthorizationResult IsAuthorized(IPrincipal principal, AuthorizationContext authorizationContext);
            protected override AuthorizationResult IsAuthorized(IPrincipal principal, AuthorizationContext authorizationContext)
            {
                Assert.IsNotNull(principal, "Principal was null when custom authorization attribute was called");
                Assert.IsNotNull(authorizationContext, "AuthorizationContext was null when custom authorization attribute was called");
                Assert.IsFalse(string.IsNullOrEmpty(authorizationContext.Operation), "Operation was blank when custom authorization attribute was called");
                Assert.IsFalse(string.IsNullOrEmpty(authorizationContext.OperationType), "OperationType was blank when custom authorization attribute was called");

                if (!string.IsNullOrEmpty(this.ExpectedOperation))
                {
                    Assert.AreEqual(this.ExpectedOperation, authorizationContext.Operation, "AuthContext.Operation was not correct when attribute was evaluated");
                }

                if (!string.IsNullOrEmpty(this.ExpectedOperationType))
                {
                    Assert.AreEqual(this.ExpectedOperationType, authorizationContext.OperationType, "AuthContext.OperationType was not correct when attribute was evaluated");
                }

                bool isInvoke = authorizationContext.OperationType.Equals("Invoke");

                AuthorizationTestEntity entity = authorizationContext.Instance as AuthorizationTestEntity;
                object instanceType = null;
                bool haveType = authorizationContext.Items.TryGetValue(typeof(Type), out instanceType);

                Assert.IsTrue(haveType, "Did not find entity type element in Items for " + authorizationContext.Operation);

                // Invokes don't guarantee the Type in the dictionary
                Assert.IsTrue(isInvoke || instanceType != null, "Entity type was null in Items diction for an Invoke");
                
                bool deny = ((!string.IsNullOrEmpty(this.DenyOperation) && this.DenyOperation.Equals(authorizationContext.Operation)) ||
                               (!string.IsNullOrEmpty(this.DenyOperationType) && this.DenyOperationType.Equals(authorizationContext.OperationType)) ||
                               (!string.IsNullOrEmpty(this.DenyInstanceValue) && entity != null && this.DenyInstanceValue.Equals(entity.TheValue)));

 
                return deny
                        ? string.IsNullOrEmpty(this.DenyMessage)
                            ? new AuthorizationResult(this.FormatErrorMessage(authorizationContext.Operation))
                            : new AuthorizationResult(this.DenyMessage)
                        : AuthorizationResult.Allowed;
            }
        public void AuthorizationContext_Ctor_From_Template()
        {
            IServiceProvider serviceProvider = new AuthorizationContextServiceProvider();
            using (AuthorizationContext template = new AuthorizationContext(serviceProvider))
            {
                // Put a known value in the template's dictionary
                IDictionary<object, object> items = template.Items;
                Assert.IsNotNull(items, "template did not autocreate Items");
                items["mockItem"] = "mockValue";

                string instance = "mockEntity";   // type is only required to be object
                string operation = "testOp";
                string operationType = "Query";

                // Call template-based ctor
                using (AuthorizationContext context = new AuthorizationContext(instance, operation, operationType, template))
                {
                    // Instance and Operation should be what the ctor set
                    Assert.AreEqual(instance, context.Instance, "AuthorizationContext.Instance property failure");
                    Assert.AreEqual(operation, context.Operation, "AuthorizationContext.Operation property failure");
                    Assert.AreEqual(operationType, context.OperationType, "AuthorizationContext.Operation property failure");

                    // Verify context delegates back to template's service provider
                    string mockStringService = (string)context.GetService(typeof(string));
                    Assert.AreEqual("mockStringService", mockStringService, "AuthorizationContext.GetService() failed to respect input service provider");

                    // The items param should have been cloned, so verify it has the same content
                    Assert.IsNotNull(context.Items, "AuthorizationContext.Items property failure");
                    Assert.IsTrue(context.Items.ContainsKey("mockItem"), "AuthorizationContext.Items failed to clone input items");
                    Assert.AreEqual("mockValue", context.Items["mockItem"], "AuthorizationContext.Items failed to set initial value correctly");

                    // Add item to original.  The snapshot in the context should be unaffected.
                    items["mockItem2"] = "mockValue2";
                    Assert.IsFalse(context.Items.ContainsKey("mockItem2"), "AuthorizationContext items should have copied snapshot input Items");

                    // Add an item to the context's Items to verify it is mutable
                    context.Items["mockItem3"] = "mockValue3";
                    Assert.IsTrue(context.Items.ContainsKey("mockItem3") && (string)context.Items["mockItem3"] == "mockValue3", "Could not modify AuthorizationContext.Items");

                    // Share logic to validate ServiceContainer
                    this.Validate_AuthorizationContext_ServiceContainer(context);
                }
            }
        }
        // Helper method to validate templates behavior
        public void Validate_AuthorizationContext_Template(AuthorizationContext context)
        {
            // Asking for Items is permitted and lazily creates a dictionary
            IDictionary<object, object> items = context.Items;
            Assert.IsNotNull(items, "Expected Items to lazily initialize");

            // Asking for Instance or Operation on a template should throw
            string expectedMessage = DataAnnotationsResources.AuthorizationContext_Template_Only;
            ExceptionHelper.ExpectInvalidOperationException(() => { var ignored = context.Instance; }, expectedMessage);
            ExceptionHelper.ExpectInvalidOperationException(() => { var ignored = context.Operation; }, expectedMessage);
            ExceptionHelper.ExpectInvalidOperationException(() => { var ignored = context.OperationType; }, expectedMessage);
        }
Example #18
0
 public bool IsAuthorized(AuthorizationContext authorizationContext)
 {
     return (UserPermissions & authorizationContext.ToPermissions()) != 0;
 }
        /// <summary>
        /// Initalizes a new instance of the <see cref="AuthorizationContext"/> class from a template that can be used for authorization.
        /// </summary>
        /// <remarks>
        /// The specified <paramref name="authorizationContext"/> will be used as the new instance's
        /// <see cref="IServiceProvider"/>, and a snapshot of its <see cref="Items"/> will be captured.
        /// </remarks>
        /// <param name="instance">Optional object instance.</param>
        /// <param name="operation">Name of the operation requiring authorization, such as "GetEmployees".</param>
        /// <param name="operationType">Kind of the operation requiring authorization, such as "Query".</param>
        /// <param name="authorizationContext">An existing <see cref="AuthorizationContext"/> to use as a template.</param>
        /// <exception cref="ArgumentNullException">When <paramref name="operation"/> or <paramref name="operationType"/> is <c>null</c> or empty
        /// or <paramref name="authorizationContext"/> is <c>null</c>.</exception>
        public AuthorizationContext(object instance, string operation, string operationType, AuthorizationContext authorizationContext)
            : this((IServiceProvider) authorizationContext)
        {
            if (authorizationContext == null)
            {
                throw new ArgumentNullException("authorizationContext");
            }

            // We use the _items field rather than the property to preserve the lazy instantiation semantics if it's null
            this.Setup(instance, operation, operationType, authorizationContext._items);
        }