Wednesday 6 November 2013

Performance Improvement without Code Change


         While fixing some of minor bugs in my project , I found out lot of database hits with same parameters , which was returning the same result. So I thought of bringing up a method where result need to be cached based on parameter. But this needs a code change in all areas, to avoid that I came up with POC for Dynamic proxy (also called as interceptor), which will be take care of the intercepting the method and will build cache and return cached value.Next fetch will be from cache when the parameters are same.

This can be implemented even when we are looking to change the whole repository fetch logic, interceptor can be plugged out when the refactoring is complete. I have used normal HTTP cache for explanatory purpose, but my code has flexible to implement any cache and its invalidating logic.

Performance is better 30 times(check image below), Result is  intercepting FormRendererRepository and NavigationRepository alone. First time load was 3.27 sec and second time load was 0.156 sec. I have used simple child form, which has Primary Navigation bar, Secondary navigation bar and two textboxes.


Advantages of using Interceptor

  • Changes to existing code is zero 
  •  Cache that needs to be used is 100% pluggable. You just need to inject the cache you need to access. All the cache access is part of developers job, so we can take measure to invalidate the Cache as per requirement.
  • You can intercept only class that you need intercepting, other classes can work without being affected
  • Since we are injecting the cache using proxy generator, Cache  can be switched on & off
  •  Any type of cache can be used and alternated depending on environment(eg.. HttpCache(ASP.Net Server) or ARP (external cache server)).

Details about Implementation

                Here I have used CastleOrg for interception and structure map for Injection. In the POC I have used form rendering where the repository calls the database for getting data. So I have intercepted the FormRepository and CentralObjectPanelRepository. The interceptor duty is to check for cache value with parameter passed when any public method is invoked. Cache key is created with method name concatenated with parameter values. If the parameter is a model then propertyname and propertyvalue is traversed and concatenated with method name(This logic can be revisited and optimized). If the created key exist in the Cache, then it’s value will be fetched from cache else the normal invocation of function takes place. Have left out the flow of saving back to cache after initial fetch for explanatory purpose.





Below class diagram explains that  ICacheprovider is pluggable, any cache mechanism that implements ICacheprovider can be part of the Interceptor mechanism.
Cache should be plugged in using below code.


var proxyGenerator = new ProxyGenerator();
            For<CacheInterceptor>();
ForRequestedType<ICacheProvider>).CacheBy(InstanceScope.Singleton).Use<HttpCache>();
For<ICentralObjectPanelRepository>().EnrichAllWith(x=>proxyGenerator.CreateInterfaceProxyWithTarget<ICentralObjectPanelRepository>(x, new CacheInterceptor()));
For<IFormRepository>().EnrichAllWith(x=> proxyGenerator.CreateInterfaceProxyWithTarget<IFormRepository>(x, new CacheInterceptor()));

Invocator has the following code while intercepting the class.



public void Intercept(IInvocation invocation)
        {
            //check if the method has a return value
            if (invocation.Method.ReturnType == typeof(void))
            {
                invocation.Proceed();
                return;
            }

            var cacheKey = BuildCacheKeyFrom(invocation);
           
            //try get the return value from the cache provider
            object item = null;
            cacheProvider.Get<object>(cacheKey,out item);

            if (item != null)
            {
                invocation.ReturnValue = item;
                return;
            }

            //call the intercepted method
            invocation.Proceed();

            if (invocation.ReturnValue != null)
            {
                cacheProvider.Set<object>(cacheKey,invocation.ReturnValue, CacheExpiryMinutes);
            }

            return;
        }

Limitation of Interceptor


·         Implementing the interceptor does no job with any of the cache functionality and it is our responsibility to implement any type of cache and how it must be invalidated.
·         Method level intercepting needs additional changes of code
·         When we have a very complex model then the parameter string formed which is used for cache key will be very huge, this can solved by ignoring the method completely for caching.

`The idea of blog is to let u know the way of doing things better using cache without any  change in existing code which will make the web page render faster

Thursday 24 October 2013

How to Implement SSO for different Application

Single sign-on (SSO) is a property of access control of multiple related, but independent software systems. With this property a user logs in once and gains access to all systems without being prompted to log in again at each of them.

 Laymen Terms: SSO is nothing but login into many applications with single user name and password

 Conversely, Single sign-off is the property whereby a single action of signing out terminates access to multiple software systems.
So as per the definition it is nothing but signing on to different application only once. I have selected THREE REAL TIME EXAMPLES in places where I have used SSO in our projects with their architectural details.

I can assure after reading this article you will be able to DESIGN ANY PROJECT which needs SSO to be implemented. Make sure you read as last Topic Cross Domain SSO, which is very important(MUST KNOW). Sample Code available here

            For all the three method below, concept is only one, multiple applications are signed with a mechanism where the authentication are persisted and maintained.

SSO Using Machine Config


This type of SSO is only done for application which is very light weight and mostly it is an intranet application that exists in same domain.

Two applications will be considered to be in same domain if their second level domain is same. look below, both the URL belongs to XyzCompany.Finance.com

• http://XyzCompany.Finance.com/app1/logon.aspx
•http:// XyzCompany.Finance.com/app2/logon.aspx

            In the above example the URL is the same and only app differs. Easy way to configure SSO in two applications is using Machine configuration file. If we have an intranet application and we want them to be SSO enabled then Machine config should suffice.

 You need to add entry in both application’s web.config and make sure both the authentication mode are same and also the numbers of parameters in the web.config are equal.
 Once the configuration is done the session is shared and the cookies are also accessible by both the application and you can access one application to another.

Step to create an SSO with MACHINE CONFIG

  1. Create a two websites with login page that has a login usercontrol that accepts user name and password.
  1. Add any authentication logic in both the application it can be as simple as below code
protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
        {
            if(Login1.UserName == "123")
            {
                e.Authenticated = true;
               FormsAuthentication.SetAuthCookie(Login1.UserName, Login1.RememberMeSet);
              }
            else
                FormsAuthentication.SignOut();
        }

Use code above in both the application. Change the username and password for the second application so it is logical to denote two different applications

  1. Open the web.config of the both the application and add the following code to the System.Web
      
         
         
      
      
         
      

4.  Add the machine.config section to the system.web



Build the application and you are done.

To test the application add the link of the first application to the second application and add the second application to the first application.

Try navigating to the First application, to ask for user name and password. Try navigating to second application, it will ask for user name and password. But if you have logged into either of the application, the other application will not ask for user name and password.

How it works

           
With the above Config settings in WEB.Config, the .NET framework uses the automatically generated validationKey and decryptionKey to create an authentication ticket and cookie. Each application uses different keys. To make multiple applications to share the same authentication ticket and cookie, we just need to set the validationKey and decrytionKey in all the applications to the same values.


Single Sign-on Within a Second Level Domain

          Next level of SSO can be done on intranet application which has different sub domain but from the same organization

 

•http://Finance.XyzCompany.com/app1/logon.aspx
•http://Payroll.XyzCompany.com/app2/logon.aspx

            In the URL’s above the organization is same but departments are different (Finance and Payroll), so we might have a different user name for accessing the sites. This type of different application for different department is common in many companies which has less employ strength.
            Use application created in Method 1 but with different url posted in IIS. In the logon.aspx use the below code to change the domain

  
//Domain name in the cookie defaults to the subdomain where the application resides
FormsAuthentication.SetAuthCookie(txtUserName.Text, false);
 
//modify the Domain attribute of the cookie to the second level domain
HttpCookie MyCookie = 
       System.Web.Security.FormsAuthentication.GetAuthCookie(User.Identity.Name.ToString(), 
                                                             false);
MyCookie.Domain = “XyzCompany.com”;//the second level domain name
Response.AppendCookie(MyCookie);

          

            Above code changes the domain of the application to have a common second level domain. Changing the domain to common “XyzCompany.com”  will make  the two application Finance.XyzCompany.com and Payroll.XyzCompany.com logged in at the same time.

 

SSO in Cross Domains Using Common database

 

            SSO in Cross domains is a common challenge that we come up in every project where we have our organization restructuring all its web projects and it needs a one common login throughout the company. It is used in two different internet application. Sample Code available here

•http://Finance.Xyz.com/app1/logon.aspx
•http://Payroll.abc.com/app2/logon.aspx

In above example the domain is different, so they cannot use any of the above two methods. We need to come up with different method where we have to implement some logic in both party to support the SSO login.

Control Flow of SSO

Step1: First the user logs in to the Payroll application.

Step2: Payroll application is authenticated by LDAP and once the authentication is successful the application takes the user to payroll’s main page.

Step3: User want to access the finance application  through the finance application link available in the main page of the payroll application. Payroll application will call the SSOAuthenticator to get the token that will be sent to the finance application for authentication as a query string. SSOAuthenticator saves the token in the common SSO Database with the login information that has been provided by the payroll application.



Step4: Payroll application will navigate the user to SSOLogon.aspx of the finance application with the token got from the SSOAuthenticator as a query string.

Step5: Once the SSOLogon.aspx page is accessed the page will then use token to validate the request, any malformation of the token or any tampering will deny the access to the finance application.

Step6: Finance application will then use the token that was send by the payroll application to get the data of the login user.

Step7:  SSOAuthenticator takes the token id and will search in the SSO database and retrieve the token’s corresponding information such as login id, that is used by the user to login and all the relevant login information will be send to the user. It also deletes the token id from the database to avoid misuse of the token by other systems.

Step8: Once the data from SSOAuthenticator is valid then the finance application sets it cookies to the login id got from the user and validates the authentication in the mainframe database of the finance. Cookies are set in the finance application for access.

Step9: User is navigated to the main page of finance application.

Implementation Details


DB Details



For simplification I have added only two tables which will be used in implementing the database details.

SSOEnabledApps table is used to store the application details where SSO is implemented, APP id acts as the identifier of the Application.

SSOAppsTokens table is used to store the SSO Token id with the application id which will be used for SSO login purpose.

Code & Configuration Details


            Below explains the implementation details. Code available @ DBBasedSSO


            User when logs into payroll application and then tries to access the finance application, the payroll application will create an token and save the token into the common SSO database using SSOAuthenticator with the SSO details. Then the token is send to the finance application through query string. Finance application then validates the token using SSOAuthenticator, and then SSOAuthenticator deletes the token from the SSO database. The user is authenticated to the finance application by setting the user cookie. Sample Code available here

Deployment Do’s and Don’t

LogonSSO.aspx, which is used for SSO Navigation where token id is passed to the page as parameter should not be part of authentication of the application. It should be outside the context of authentication. Use the below config to have logonSSO.aspx page being disabled from authentication. Place the below configuration after </system.web>

<location path="LogonSSO.aspx">
    <system.web>
      <authorization>
        <allow users ="*" />
        <allow users="?"/>
      </authorization>
    </system.web>
  </location>

  While accessing logonSSO.aspx, if the application still navigates to authentication page (login.aspx), try rebuilding the solution (Worked for me)

Concerns overseen

·         Sooner or later Data becomes out of sync.
·         Changes occurring in our database cannot be transferred to the SSO database until the next scheduled run. Therefore, the third party database is not up to date.
·         There is a need to create a different data transfer mechanism for each SSO database due to different business requirements. It is difficult to manage the multiple data sync processes.

            In this article we have seen three kinds of SSO with First level, second level and cross domain. All three levels have their significance of its own and it should be chosen as per the requirement. Cross domain authentication is widely used; methods described above are only for mere understanding. The DB design and the flow can alter as per the requirement, because lots of issues arise in real time application and it should be handled on case to case basics. You can get the code for Cross domain SSO @ DBBasedSSO

Leave a comment to share what you learned, and hit the “like” button to let others know about it (make sure you’re logged into Facebook to like and comment). 





Build Bot using LUIS