Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How to Enable AD FS Authentication (Part 2)

DZone's Guide to

How to Enable AD FS Authentication (Part 2)

Want to learn more about how to enable AD FS authentication on your web application? Check out part two of this tutorial to learn more!

· Security Zone ·
Free Resource

Discover how to provide active runtime protection for your web applications from known and unknown vulnerabilities including Remote Code Execution Attacks.

Introduction

In part two of this series on how to enable AD FS authentication, we are going to learn more about the implementation of AD FS.

These are the steps that demonstrate the necessary precautions for a web application to make claims-based authorization decisions using AD FS. AzMan, a Windows Authorization Manager, is used to provide role-based access control via the acronym RBAC. The development tasks are:

Making the Application Federation-Aware

To make an application federation-aware, the following changes are required for its Web.config file. Once these changes are made, an application can then obtain claims from AD FS for the federation partners. It is important to make sure that the web application must also be identified and configured within the AD FS snap-in, which thus enables both the federation service and the .net application development to securely identify each other.

AD FS Web Agent Registration

AD FS provides a tool called the Web Agent. This tool runs in the IIS request pipeline as an extension HTTP module of type System.Web.Security.SingleSignOn.WebSsoAuthenticationModule. The AD FS Web Agent registers a handler for the HttpApplication.BeginRequest event that performs all the processing for query strings, cookies, and HTTP POST messages. It then obtains the identity or the security token of the user and decides whether to permit access to the application. An application must add the AD FS Web Agent to the web server or the modules section of its Web.config file, as shown in the below XML example.

 <webServer>  
  <modules>  
   <add name="Adfs Web Agent"  
     type="System.Web.Security.SingleSignOn.WebSsoAuthenticationModule,  
        System.Web.Security.SingleSignOn,  
        Version=1.0.0.0, Culture=neutral,  
        PublicKeyToken=31BF3856AD364E35, Custom=null" />  
  </modules>  
 </webServer>  


Custom Configuration Section and Handler Specification

The AD FS Web Agent needs to access the settings stored, which are in the Web.config file and uses a configuration section handler of type System.Web.Security.SingleSignOn.WebSsoConfigurationHandler to do so. These settings are stored in a custom section called the Web SSO. Then, the configuration file handler must be made aware of the custom section by specifying the section in the system.web section group, which is as shown in the following XML example:

 <configSections>  
  <sectionGroup name="system.web">  
   <section name="websso"  
        type="System.Web.Security.SingleSignOn.WebSsoConfigurationHandler,  
           System.Web.Security.SingleSignOn,  
           Version=1.0.0.0, Culture=neutral,  
           PublicKeyToken=31BF3856AD364E35, Custom=null" />  
  </sectionGroup>  
 </configSections>  


Add the Custom Section

In the custom web SSO section, the settings required by the AD FS Web Agent are specified and described in the following table.

Setting Value
FS

It is the URL for the resource AD FS server.

returnurl

It is the URL for a Web application, which is used by the AD FS Web Agent to redirect the user back to a Web application after validation.

The return URL that must match the Application URL. And that is specified in the Web application's properties page i.e. in the AD FS snap-in which is located under Federation Service\Trust Policy\My Organization\Applications.

cookies/path

It is the path of the virtual directory for this Web application; case sensitive.

authenticationrequired

IT specifies whether authentication is required to access the Web application or not. The default is true, in which case the user cannot access the Web application without a valid AD FS cookie. When this element is missing or false, the user can then access the Web application anonymously.

 <websso>  
  <fs>https://someresourcefederationserver/adfs/fs/federationserverservice.asmx</fs>  
  <urls>  
   <returnurl>https://localhost/TreyOrdering/Default.aspx</returnurl>  
  </urls>  
  <cookies writecookies="true">  
   <path>/TreyOrdering</path>  
  </cookies>  
  <authenticationrequired />  
 </websso>  


Reference the SingleSignOn Assemblies

Then, we have added references for the System.Web.Security.SingleSignOn  and System.Web.Security.SingleSignOn.ClaimTransforms assemblies to enable the web application to access types in the System.Web.Security.SingleSignOn and System.Web.Security.SingleSignOn.Authorization namespaces, respectively.
Then, we also need to set the authentication mode to “None,” since authentication is performed by AD FS and not Internet Information Services (IIS).

 <system.web>  
  <authentication mode="None" />  
  <compilation defaultLanguage="c#" debug="true">  
   <assemblies>  
    <add assembly="System.Web.Security.SingleSignOn,  
            Version=1.0.0.0, Culture=neutral,  
            PublicKeyToken=31BF3856AD364E35"/>  
    <add assembly="System.Web.Security.SingleSignOn.ClaimTransforms,  
            Version=1.0.0.0, Culture=neutral,  
            PublicKeyToken=31BF3856AD364E35"/>  
   </assemblies>  
  </compilation>  
 </system.web>  


Obtain the SingleSignOnIdentity Object

Next, in the code for the web application, we should include the System.Web.Security.SingleSignOn namespace, which contains the SingleSignOnIdentity class, and the System.Web.Security.SingleSignOn.Authentication namespace, which contains the SecurityProperty and SecurityPropertyCollection classes. These namespaces help enable the application to use the AD FS infrastructure for authentication and access the claims it provides via the SAML token.

 using System.Web.Security.SingleSignOn;

using System.Web.Security.SingleSignOn.Authorization; 

Set the the SingleSignOnIdentity  object on the HttpContext.User property by the AD FS Web Agent, i.e. the WebSsoAuthenticationModule. An application obtains the SingleSignOnIdentity object during the Page_Load  event of the page life cylcle.

 private void Page_Load(object sender, System.EventArgs e) 
 { 
 SingleSignOnIdentity SsoId = User.Identity as SingleSignOnIdentity; 
 } 

Verify Authentication

The Web.config file for this example also includes the  authenticationrequired element, which, by default, has true value. This tells the AD FS Web Agent that the specified user must be authenticated before access to the web application is granted. If the authenticationrequired element is not present or set to false, then the user can access the application anonymously. In case anonymous access is granted, use the SingleSignOnIdentity.IsAuthenticated property to check for authenticating the user.

 if (SsoId.IsAuthenticated)  
 {  
   // ...   
 }  
 else  
 {  
   // Otherwise, this redirects the user to the resource AD FS Logon service.  
   SsoId.SignIn(Context);   
 }  


Sometimes, whoever provided the authentication might be an important consideration before trust is granted to the user. You can use the SingleSignOnIdentity.AuthenticatingAuthority property for this.

Create a Client Context Using AzMan

The following code example illustrates how to connect to the AzMan trust policy store, obtain an object that represents this application's trust policy in the AzMan store, and create an empty client context. Subsequently, the client context will be populated with Group claims and used to make authorization decisions.

 string connectionString = @"msxml://c:\AuthPolicy\AzStore.xml";  
 // Connect to the AzMan authorization policy store.  
 AzAuthorizationStoreClass azStore = new AzAuthorizationStoreClass();  
 azStore.Initialize(0, connectionString, null);  
 // Obtain the object associated with this application.  
 IazApplication2 azApplication =   
   azStore.OpenApplication("Trey Ordering", null);  
 // Create an empty client context.  
 IAzClientContext3 clientContext =   
   azApplication.InitializeClientContext2("Trey Ordering", null);  


Retrieve Claims

The System.Web.Security.SingleSignOn.Authentication namespace contains the SecurityProperty and SecurityPropertyCollection classes. The SingleSignOnIdentity.SecurityPropertyCollection property returns a SecurityPropertyCollection instance, which contains a SecurityProperty object for each claim about the user. Group claims are added as roles to the AzMan client context. Identity and custom claims are added to a NameValueCollection object for convenient retrieval.

 SecurityPropertyCollection claims = SsoId.SecurityPropertyCollection;  
 // Add all Group claims (as roles) to the AzMan client context.  
 clientContext.AddRoles(claims.GetRoles(), null);  
 // Store identity and custom claims in a NameValueCollection.  
 foreach (SecurityProperty claim in claims.GetIdentities())  
 {  
   nonGroupClaims.Add(claim.Name, claim.Value);  
 }  
 foreach (SecurityProperty claim in claims.GetProperties(  
   SecurityProperty.CustomClaimUri))  
 {  
   nonGroupClaims.Add(claim.Name, claim.Value);  
 }  


Make Authorization Decisions

There are many ways to make authorization decisions. Three of the more common are discussed here:

  • Using raw claims
  • Using role checks
  • Using access checks

Access checks are preferable and make the application less coupled with policy.

Raw Claims

Raw claims from AD FS can be availed through the SecurityPropertyCollection object. The following code example shows a decision based on the custom claim named EmployeeID, which, in the previous section, was retrieved and added to the nonGroupClaims NameValueCollection. Raw claims can be used in along with role and access checks.

 if (Convert.ToInt32(nonGroupClaims["EmployeeID"]) == 321) 

 { 

 // Allow access. 

 } 

Role Checks

The easiest means to make authorization decisions is to base them on roles using the IPrincipal.IsInRole method, which is available through HttpContext.User or the SecurityPropertyCollection.IsInRole method. The IsInRole property returns true if there is a Group claim equal to the role. Role checks do not provide the granularity that access checks allow.

 if (User.IsInRole("Purchaser"))  
 {  
   // Allow access.  
 }  
 -or-  
 if (claims.IsInRole("Purchaser"))  
 {  
   // Allow access.  
 }  


The client context obtained through AzMan can also be used for role checks, as the following code snippet demonstrates.

 if (clientContext.IsInRoleAssignment("", "Purchaser") ) 

 { 

 // Allow access. 

 } 

Access Checks

AzMan is a tool used for access checks. It allows authorizations to be made based on specific operations, which are defined in the AzMan authorization policy store. In the following code example, access is granted to any user in an AzMan role (Group claim) that is allowed to perform operation #57.

 // 57 corresponds to an OperationID defined in the AzMan store. 

 if (clientContext.AccessCheck2("Order #123", "", 57) == 0) 

 { 

 // Allow access for operation #57. 

 } 


Conclusion

In part one, we learned the concepts behind AD FS authentication, and in this article, we learned the implementation. There are more things to learn about AD FS, but we just got started with some important concepts and implementation details. 

Happy coding!

Find out how Waratek’s award-winning application security platform can improve the security of your new and legacy applications and platforms with no false positives, code changes or slowing your application.

Topics:
asp.net ,security ,single sign on ,sso ,web sso ,authentication ad fs ,authentication ,ad fs ,web security ,tutorial

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}