Authorization

patterns & practices Developer Center

  • How to: Authorize Declaratively
  • How to: Authorize Imperatively if You Use a Role Provider
  • How to: Authorize Imperatively
  • How to: Perform Resource-based Authorization
  • How to: Perform Role-based Authorization
  • How to: Authorize Users Against Windows Groups
  • How to: Authorize Users Against Windows Groups Using Aspnetwindowstokenroleprovider
  • How to: Authorize Users Against the SQL Server Role Provider
  • How to: Authorize Users Against the ASP.NET Role Provider
  • How to: Assign the Current Principal with Iauthorizationpolicy to Allow Authorization Using Custom Authentication
  • How to: Authorize Users Against ADAM Using the Authorization Manager Role Provider
  • How to: Map Roles to Certificates

How to: Authorize Declaratively

Declarative authorization can be added to application code at design time by specifying required access for a particular method or class declared as an attribute on the operation. Declarative role-based authorization is best for authorizing access to WCF at the operation level. Declarative authorization can be added to application code at design time by specifying required access for a particular method or class declared as an attribute on the operation.

Authorize Windows groups declaratively by adding the PrincipalPermission attribute above each service method that requires authorization. Specify the Windows user group required to access the method in the Role field as shown in the following example:

[PrincipalPermission(SecurityAction.Demand, Role = "accounting")]
public double Add(double a, double b)
{
    return a + b;
}

The username/password combination supplied by the client will be mapped to a Windows user account by the WCF service. If the user is successfully authorized, the system will next check to see if the user belongs to the group declared with the PrinciplePermission role. Method access will be granted if the user belongs to the role.

Additional Resources

How to: Authorize Imperatively if You Use a Role Provider

If you are using a role provider, you can do imperative checks by calling Roles.isUserInRole. If you are using the AspNetWindowsToken Role Provider, you can use imperative authorization against Windows roles. Imperative security is useful when the resource to be accessed or action to be performed is not known until run time, or when you require finer-grained access control beyond the level of a code method.

Authorize Windows groups or roles that can be SQL or custom roles imperatively by using the Roles.IsUserInRole method to authorize the client. The role can be contained in a variable and changed dynamically if needed, as shown in the following example:

  string RequiredGroup = "Administrators";
  try
  {
    if (!Roles.IsUserInRole(User.Identity.Name, "RequiredGroup"))
    {
      Msg.Text = "You are not authorized to view user roles.";
      UsersListBox.Visible = false;
      return;
    }
  }
  catch (HttpException e)
  {
    Msg.Text = "There is no current logged on user. Role membership cannot be verified.";
    return;
  }

Additional Resources

How to: Authorize Imperatively

Imperative role-based authorization is written into your code and processed at run time. Imperative security is useful when the resource to be accessed or action to be performed is not known until run time, or when you require finer-grained access control beyond the level of a code method.

Authorize Windows groups imperatively by using the principal.IsInRole method. The following code snippet exemplifies the authorization check:

string RequiredGroup = "Administrators";
 IPrincipal principal=System.Threading.Thread.CurrentPrincipal;
        if (principal.IsInRole(RequiredGroup))
            return string.Format("You entered: {0}", value);
        else
            return "not authorized";  

Additional Resources

How to: Perform Resource-based Authorization

Resource-based authorization sets permissions on the resource itself. For example, you would set an access control list (ACL)on a Windows resource and then use the identity of the original caller to determine access rights to the resource. If you use resource-based authorization in WCF, you will need to impersonate the original caller through the application layer (e.g., ASP.NET application), through the WCF service layer, and to the business logic code that is accessing the file resource.

To use resource-based authorization, you need to set permissions on the resource itself by setting an ACL and then impersonating the original caller.

The following code example impersonates a specific (fixed) identity:

using System.Security.Principal;
…
WindowsIdentity wi = new WindowsIdentity(“userName@fullyqualifieddomainName”);
WindowsImpersonationContext ctx = null;

try
{
  ctx = wi.Impersonate();

  // Thread is now impersonating you can access resource needed…
}
catch
{
  // Prevent exceptions propagating.
}
finally
{
  // Ensure impersonation is reverted
  ctx.Undo();
}

Additional Resources

  • For more information on authorization, see Authorization.
  • For authorization guidelines, see the Authorization section of WCF Security Guidelines.

How to: Perform Role-based Authorization

Use role-based authorization to group users into groups (roles) and then set permissions on the role rather than on individual users. This eases management by allowing you to administer a smaller set of roles rather than a larger set of users.

The following are the different options for creating role-based authorization based on your authentication choice:

  • If you are using Windows or Basic authentication, you can use Windows groups for role-based authorization.
  • If you are using username authentication, you can use ASP.NET roles for role-based authorization.
  • If you are using certificate authentication, you can map certificates to Windows groups for role-based authorization.

The following example configures the service to enable the SQL Server role provider for using ASP.NET roles:

  1. Configure the SQL Server role provider:

        <!-- Configure the Sql Role Provider -->
        <roleManager enabled ="true" 
                     defaultProvider ="SqlRoleProvider" >
          <providers>
            <add name ="SqlRoleProvider" 
                 type="System.Web.Security.SqlRoleProvider" 
                 connectionStringName="SqlConn" 
                 applicationName="MembershipAndRoleProviderSample"/>
          </providers>
        </roleManager>
        <!-- Configure role based authorization to use the Role Provider -->
        <serviceAuthorization principalPermissionMode ="UseAspNetRoles"
                              roleProviderName ="SqlRoleProvider" />
    
  2. Include a PrincipalPermission attribute in the service method that specifies the required authorization access role:

        [PrincipalPermission(SecurityAction.Demand, Role = "Registered Users")]
        public double Multiply(double n1, double n2)
          {
             double result = n1 * n2;
             return result;
          }
    
  3. The following code shows how to create the authorization check in code:

    if (Roles.IsUserInRole(@"accounting"))
    {
    //authorized
    }
    else
    {
    //authorization failed
    
    }
    
  4. The following client connection supplies a username and password to call the method:

          // Set credentials to Alice
          client.ClientCredentials.UserName.UserName = "Alice";
          client.ClientCredentials.UserName.Password = "ecilA-123";
    
          // Call the Add service operation.
          double value1 = 100.00D;
          double value2 = 15.99D;
          double result = client.Multiply(value1, value2);
    

Additional Resources

  • For more information on authorization, see Authorization.
  • For authorization guidelines, see the Authorization section of WCF Security Guidelines.

How to: Authorize Users Against Windows Groups

Map Windows groups to WCF service methods by using the WCF PrincipalPermission attribute. Incoming client username credentials will be mapped to the associated Windows group. Service method access will be granted to a user only if they are a member of the group associated with the service method being called.

The following example demonstrates how the WCF service “Add” will only run for users belonging to the “CalculatorClients” Windows group.

// Only members of the CalculatorClients group can call this method.
[PrincipalPermission(SecurityAction.Demand, Role = "CalculatorClients")]
public double Add(double a, double b)
{
    return a + b;
}

Additional Resources

  • For more information on authorization, see Authorization.
  • For authorization guidelines, see the Authorization section of WCF Security Guidelines.

How to: Authorize Users Against Windows Groups Using AspNetWindowsTokenRoleProvider

If you use Windows groups for authorization, consider using the ASP.NET role provider with the AspNetWindowsTokenRoleProvider name. This allows you to separate the design of the authorization from the implementation inside your service. If you decide to change the role provider, it will not affect the code needed to perform the authorization. Also, when doing imperative checks, consider using the role manager API instead of performing authorization checks with WindowsPrincipal.IsInrole.

The following configuration example shows how to configure AspNetWindowsTokenRoleProvider:

  1. Enable the role manager and configure it to use the default AspNetWindowsTokenRoleProvider as follows:

    <system.web>
    …
    <roleManager enabled="true"
    defaultProvider="AspNetWindowsTokenRoleProvider" />
    …
    </system.web>
    
  2. Configure the service behavior to use AspNetRoles and the role provider as follows:

    <behaviors>
        <serviceBehaviors>
            <behavior name="BehaviorConfiguration">
                <serviceAuthorization principalPermissionMode="UseAspNetRoles"
                    roleProviderName=" AspNetWindowsTokenRoleProvider " />
                <serviceMetadata />
            </behavior>
        </serviceBehaviors>
    </behaviors>
    

Additional Resources

How to: Authorize Users Against the SQL Server Role Provider

If you store role information in SQL Server, configure your application to use SqlRoleProvider for authorization. The role provider allows you to load the roles for users without writing and maintaining custom code.

Perform the following steps to enable SQL Server role authorization to provide role-based authorization:

  1. Enable the role provider as shown below and configure the connection string pointing to the role store in SQL Server:

    …
    <configuration>
    …
    <connectionStrings>
        <add name="MyLocalSQLServer"
             connectionString="Initial Catalog=aspnetdb;data source=Sqlserver;Integrated Security=SSPI;" />
         </connectionStrings>
    
    <system.web>
    <roleManager enabled="true" defaultProvider="MySqlRoleProvider" >
          <providers>
            <add name="MySqlRoleProvider"
                 connectionStringName="MyLocalSQLServer"
                 applicationName="MyAppName"
                 type="System.Web.Security.SqlRoleProvider" />
          </providers>
        </roleManager>
    <system.web>
    
  2. Configure the service behavior. Set the principalPermissionMode attribute to UseAspNetRoles and the roleProviderName attribute to MySqlRoleProvider:

    …
    <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior name="BehaviorConfiguration">
              <serviceAuthorization principalPermissionMode="UseAspNetRoles"
                roleProviderName="MySqlRoleProvider" />          
             </behavior>
          </serviceBehaviors>
        </behaviors>
    <services>
        <service behaviorConfiguration=" BehaviorConfiguration " name="MyService">
          <endpoint binding="wsHttpBinding" bindingConfiguration=""
            name="httpsendpoint" contract="IMyService2" />
         </service>
      </services>
      </system.serviceModel>
    
  3. Authorize Windows groups declaratively by adding the PrincipalPermission attribute above each service method that requires authorization. Specify the Windows user group required to access the method in the Role field:

    [PrincipalPermission(SecurityAction.Demand, Role = "accounting")]
    public double Add(double a, double b)
    {
        return a + b;
    }
    

Additional Resources

  • For more information on authorization, see Authorization.
  • For authorization guidelines, see the Authorization section of WCF Security Guidelines.

How to: Authorize Users Against the ASP.NET Role Provider

Using the ASP.NET role provider allows you to separate the design of the authorization from the implementation inside your service. If you decide to change the role provider, it will not affect the code needed to perform the authorization.

Declaratively authorize users with the ASP.NET role provider

Perform the following steps to declaratively authorize users with the ASP.NET role provider:

  1. Configure the ASP.NET role provider in the service app.config or web.config file as follows:

      <system.web>
        <!-- Configure the ASP.NET Role Provider -->
        <roleManager enabled ="true" 
                     defaultProvider ="MyRoleProvider" >
          <providers>
            <add name ="MyRoleProvider" 
                 type="System.Web.Security.<RoleProviderTobeUsed>" 
                 connectionStringName="ProviderConn" 
                 applicationName="MembershipAndRoleProviderSample"/>
          </providers>
        </roleManager>
      </system.web>
    
  2. Configure the WCF service to use the ASP.NET role:

        <behaviors>
          <serviceBehaviors>
            <behavior name="CalculatorServiceBehavior">
               <!-- Configure role based authorization to use --> 
               <!-- the Role Provider -->
              <serviceAuthorization 
                   principalPermissionMode ="UseAspNetRoles"
                   roleProviderName ="MyRoleProvider" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
  3. Authorize users declaratively by adding the PrincipalPermission attribute above each service method that requires authorization. Specify the user role required to access the method in the Role field.

    [PrincipalPermission(SecurityAction.Demand, Role = "accounting")]
    public double Add(double a, double b)
    {
        return a + b;
    }
    

Imperatively authorize users with the ASP.NET role provider

Perform the following steps to imperatively authorize users with the ASP.NET role provider:

  1. Configure the ASP.NET role provider in the service app.config or web.config file as follows:

      <system.web>
        <!-- Configure the ASP.NET Role Provider -->
        <roleManager enabled ="true" 
                     defaultProvider ="MyRoleProvider" >
          <providers>
            <add name ="SqlRoleProvider" 
                 type="System.Web.Security.<RoleProviderToBeUsed>" 
                 connectionStringName="ProviderConn" 
                 applicationName="MembershipAndRoleProviderSample"/>
          </providers>
        </roleManager>
      </system.web>
    
  2. Configure the WCF service to use the ASP.NET role provider:

        <behaviors>
          <serviceBehaviors>
            <behavior name="CalculatorServiceBehavior">
              <!-- Configure role based authorization --> 
              <!-- to use the Role Provider -->
              <serviceAuthorization principalPermissionMode ="UseAspNetRoles"
                                    roleProviderName ="MyRoleProvider" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
  3. Authorize users imperatively by using the Roles.IsUserInRole method. The role can be contained in a variable and changed dynamically if needed, as shown in the following example:

      string RequiredGroup = “Administrators”;
      try
      {
        if (!Roles.IsUserInRole(User.Identity.Name, “RequiredGroup”))
        {
          Msg.Text = "You are not authorized to view user roles.";
          UsersListBox.Visible = false;
          return;
        }
      }
      catch (HttpException e)
      {
        Msg.Text = "There is no current logged on user. Role membership cannot be verified.";
        return;
      }
    

Additional Resources

How to: Assign the Current Principal with IAuthorizationPolicy to Allow Authorization Using Custom Authentication

If your application uses custom authentication, you will need to create a class that derives from IAuthorizationPolicy. In this class, you will retrieve the principal from the cache that was created by the custom authentication, or from the store based on the username, so that WCF can authorize the user. After you get the principal, you assign it to EvaluationContext.Properties[“principal”] and the identity to EvaluationContext.Properties["Identities"] as shown in the following example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IdentityModel.Claims;
using System.IdentityModel.Policy;
using System.Web;
using System.Security.Principal;
using CustomAuthenticator;



namespace AuthorizationPolicy
{
   public class AuthorizationPrincipalPolicy : IAuthorizationPolicy
   {
      public bool Evaluate(EvaluationContext evaluationContext, ref 
        object state)
        {
            object obj;
            if (!evaluationContext.Properties.TryGetValue("Identities",
                out obj))
                return false;
            IList<IIdentity> identities = obj as IList<IIdentity>;

            // make sure there is already a default identity
            if (identities == null || identities.Count <= 0)
                return false;


            string username = identities[0].Name;

            //get the principal from the cache or build another one  

            IPrincipal principal = 
            UserNameAuthenticator.GetUser(username);

            if (principal == null)
            {
                string[] roles = 
                UserNameAuthenticator.GetRolesForUser(username);
                principal = new GenericPrincipal(new 
                GenericIdentity(username, "Custom Provider"), roles);

            }

            evaluationContext.Properties["Principal"] = principal;
            evaluationContext.Properties["Identities"] =
                   new List<IIdentity>() { principal.Identity };


            return true;
        }

        public System.IdentityModel.Claims.ClaimSet Issuer
        {
            get { return ClaimSet.System; }
        }

        public string Id
        {
            get { return "ContextPrincipalPolicy"; }
        }
    }
}

The Policy library is configured in the web.config or app.config configuration file or in code. The following example configures the policy location in the configuration file. Define the custom authorization policy type in the add element policyType attribute.

<serviceAuthorization 
    serviceAuthorizationManagerType
    ="Microsoft.ServiceModel.Samples.MyServiceAuthorizationManager, service">
    <!-- The serviceAuthorization behavior allows one to specify custom authorization policies. -->
<authorizationPolicies>

        <add policyType
="Microsoft.ServiceModel.Samples.CustomAuthorizationPolicy.MyAuthorizationPolicy, PolicyLibrary" />
</authorizationPolicies>

</serviceAuthorization>

Additional Resources

How to: Authorize Users Against ADAM Using the Authorization Manager Role Provider

If your application stores role information in an Authorization Manager (AzMan) policy store in Active Directory Application Mode (ADAM), use the Authorization Manager role provider. Authorization Manager provides a Microsoft Management Console (MMC) snap-in to create and manage roles, and to manage role membership for users.

Perform the following steps to authenticate a directory service with ADAM:

  1. Use AzMan to store roles in an ADAM policy store as follows.

    Note

    You can only currently create an ADAM store within Microsoft Windows Server® 2003.

    1. At the command prompt, type azman.msc to open the Authorization Manager snap-in.
    2. In AzMan, right-click Authorization Manager and then click New Authorization Store. Select Active Directory and enter a name to create the ADAM store.
    3. Right-click the Groups folder of the Active Directory store you just created, and then click New Application Group. Enter a name for the group you want to create. Repeat this step to create as many groups as needed.
    4. Add Windows users to the AzMan groups(s) you created. Double-click each group you created and use the Members tab to add the users.
  2. Configure the web.config or app.config file to use the ADAM store. Define a connection string to the AzMan policy store in ADAM and configure the WCF service to use the role provider as follows.

    <ConnectionStrings>
    
       <add name="AzManADAMServer" connectionString=
    "msldap://servername:port/CN=AzManADAMStore,OU=SecNetPartition,O=SecNet,C=US"/>
    </ConnectionStrings>
    
    <system.web>
    <roleManager 
        enabled="true" 
        defaultProvider="RoleManagerAzManADAMProvider"
        <providers>
            <add name="RoleManagerAzManADAMProvider"
         type="System.Web.Security.AuthorizationStoreRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, 
                 publicKeyToken=b03f5f7f11d50a3a"
                 connectionStringName="AzManADAMServer" 
                 applicationName="AzManDemo"/>
        </providers>
    </roleManager>
    </system.web>
    
  3. Configure the service behavior. Set the principalPermissionMode attribute to UseAspNetRoles and the roleProviderName attribute to RoleManagerAzManADAMProvider:

    …
    <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior name="BehaviorConfiguration">
              <serviceAuthorization principalPermissionMode="UseAspNetRoles"
                roleProviderName="RoleManagerAzManADAMProvider" />          
             </behavior>
          </serviceBehaviors>
        </behaviors>
    …
      </system.serviceModel>
    
  4. Authenticate the users declaratively by adding the PrincipalPermission attribute above each service method that requires authorization. Specify the Windows user group required to access the method in the Role field.

    [PrincipalPermission(SecurityAction.Demand, Role = "accounting")]
    public double Add(double a, double b)
    {
    return a + b;
    }
    

The username/password combination supplied by the client will be mapped by the WCF service to a Windows user account. If the user is successfully authorized, the system will next check to see if the user belongs to the group declared with the PrinciplePermission role. Method access will be granted if the user belongs to the role.

Additional Resources

How to: Map Roles to Certificates

If you are using certificate authentication, you can map the certificate to a Windows account and authorize based on this account.

Perform the following steps to associate roles with a certificate:

  1. Configure IIS to enable client certificate mapping.

    1. Open the IIS service manager.
    2. Right-click the Web site you will be using for your service and then click Properties.
    3. Click the Directory Security tab, and then in the Secure Communications section, click Edit.
    4. Select the Enable Client Certificate Mapping check box. Click the Edit button and then enter 1-1 or Many-to-1, depending on your configuration.
  2. Configure the service to require ClientCredentialType = “Certificate”.

    This will require clients to connect by using certificate authentication.

          <message clientCredentialType="Certificate" />
    
  3. Configure the service to map certificates to user accounts in the web.config or app.config file. Set the mapClientCertificateToWindowsAccount to “true” as follows:

    <serviceBehaviors>
     <behavior name="MappingBehavior">
      <serviceCredentials>
       <clientCertificate>
        <authentication certificateValidationMode="None"   
                        mapClientCertificateToWindowsAccount="true" />
       </clientCertificate>
      </serviceCredentials>
     </behavior>
    </serviceBehaviors>
    
  4. Configure clients to supply a certificate as shown below.

    The incoming client requests will contain a certificate name and thumbprint ID. IIS will map the client certificates to a Windows user account.

          <message clientCredentialType="Certificate" />
    
  5. Authorize the required Windows group by adding the PrincipalPermission attribute above each service method that requires authorization. Specify the Windows user group required to access the method in the Role field as shown in the following example.

    [PrincipalPermission(SecurityAction.Demand, Role = "accounting")]
    public double Add(double a, double b)
    {
        return a + b;
    }
    

Additional Resources

  • For more information on authorization, see Authorization.
  • For authorization guidelines, see the Authorization section of WCF Security Guidelines.