Showing posts with label Code. Show all posts
Showing posts with label Code. Show all posts

Wednesday, September 11, 2013

Integrate OpenAuth/OpenID with your existing ASP.NET application using Universal Providers

Over the past couple of weeks I have come across lots of questions/discussions on while OAuth/OpenId is cool as a feature in the ASP.NET templates in Visual Studio 2012, but how do I easily integrate this into my application outside of the templates. More so how do I extend the Universal Providers to integrate OAuth/OpenId and use other functionality such as roles etc. I am going to cover these two areas in this post using WebForms but you could integrate the same with MVC applications as well
Update
While the post is titled to show how you can integrate this with UniversalProviders, you can totally integrate this with SqlMembership or with your custom membership providers since Microsoft.AspNet.Membership.OpenAuth uses Membership APIs for creating users and login
I posted the following webforms project template which uses sqlmembership
https://github.com/rustd/AspNetSocialLoginSqlMembership

Following are the steps of integrating OpenAuth/OpenId into your existing application

    • I started with an empty 4.5 webapplication(yes nothing in my project except a web.config)
    • Use Nuget to get the following packages
      • DotNetOpenAuth.AspNet
        • This package is the core package for OAuth/OpenID protocol communication
      • Microsoft.AspNet.Providers.Core
        • This package brings in Universal Providers
      • Microsoft.AspNet.Providers.LocalDb
        • This package sets the connectionstring for the Universal Providers
      • Microsoft.AspNet.Membership.OpenAuth
        • This package provides the extension to integrate OAuth/OpenID with Membership providers
    • Change web.config to use formsauthentication
<authentication mode="Forms">
     <forms loginUrl="Default.aspx"></forms>
</authentication>
    • In App_Start Register the list of OAuth/OpenId providers you want to use. By convention any application_start registration is done in a folder called App_Start
// See http://go.microsoft.com/fwlink/?LinkId=252803 for details on setting up this ASP.NET
            // application to support logging in via external services.
 
            //OpenAuth.AuthenticationClients.AddTwitter(
            // consumerKey: "your Twitter consumer key",
            // consumerSecret: "your Twitter consumer secret");
 
            //OpenAuth.AuthenticationClients.AddFacebook(
            // appId: "your Facebook app id",
            // appSecret: "your Facebook app secret");
 
            //OpenAuth.AuthenticationClients.AddMicrosoft(
            // clientId: "your Microsoft account client id",
            // clientSecret: "your Microsoft account client secret");
 
            OpenAuth.AuthenticationClients.AddGoogle();

    • Create a page to display the list of providers to use for logging in(This page reads the list configured in App_Start) In my sample I created Default.aspx.
      • Markup
<asp:ListView runat="server" ID="providerDetails" ItemType="Microsoft.AspNet.Membership.OpenAuth.ProviderDetails"
             SelectMethod="GetProviderNames" ViewStateMode="Disabled">
             <ItemTemplate>
                 <button type="submit" name="provider" value="<%#: Item.ProviderName %>"
                     title="Log in using your <%#: Item.ProviderDisplayName %> account.">
                     <%#: Item.ProviderDisplayName %>
                 </button>
             </ItemTemplate>
             <EmptyDataTemplate>
                 <p>There are no external authentication services configured. </p>
             </EmptyDataTemplate>
         </asp:ListView>
      • Code
public IEnumerable<ProviderDetails> GetProviderNames()
     {
         return OpenAuth.AuthenticationClients.GetAll();
     }
At this stage the UI will look as follows
providers

    • Request a call to the OpenID/OAuth provider for RequestAuthentication. This code will make an outbound call to the provider where a user can enter the login details and the provider will call back to the app’s return url
public string ReturnUrl { get; set; }
 
        protected void Page_Load(object sender, EventArgs e)
        {
            if (IsPostBack)
            {
                var provider = Request.Form["provider"];
                if (provider == null)
                {
                    return;
                }
 
                var redirectUrl = "~/ExternalLoginLandingPage.aspx";
                if (!String.IsNullOrEmpty(ReturnUrl))
                {
                    var resolvedReturnUrl = ResolveUrl(ReturnUrl);
                    redirectUrl += "?ReturnUrl=" + HttpUtility.UrlEncode(resolvedReturnUrl);
                }
 
                OpenAuth.RequestAuthentication(provider, redirectUrl);
            }
        }
At this stage the UI will look as follows
googlelogin
    • Now when the provider calls back to the app, we have to check whether the user was authenticated without any errors and if so then login the user. In my sample user I configured the returnurl to be ExternalLoginLandingPage.aspx so create a page called ExternalLoginLandingPage in the root of your app. This page serves the following functions(For brevity, I am pasting in relevant methods/markup here. This entire sample is posted on my github repository https://github.com/rustd/SocialLoginASPNET)
      1. Display the authenticated username from the provider and verify if the authentication from provider succeeded or not(eg. did you enter correct username/password)
ProcessProviderResult() in page_load does this processing
      1. localaccount
      2. You can set the local username of the user if you want to and create the membership user and associate the OAuth/OpenID and save this to the database
//Markup and refer to codebeind methods
<ol>
               <li class="email">
                   <asp:Label ID="Label1" runat="server" AssociatedControlID="userName">User name</asp:Label>
                   <asp:TextBox runat="server" ID="userName" />
                   <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="userName"
                       Display="Dynamic" ErrorMessage="User name is required" ValidationGroup="NewUser" />                    
                   <asp:ModelErrorMessage ID="ModelErrorMessage2" runat="server" ModelStateKey="UserName" CssClass="field-validation-error" />                    
               </li>
           </ol>
           <asp:Button ID="Button1" runat="server" Text="Log in" ValidationGroup="NewUser" OnClick="logIn_Click" />
           <asp:Button ID="Button2" runat="server" Text="Cancel" CausesValidation="false" OnClick="cancel_Click" />
At this stage the UI will look as follows
loggedin

Database structure

Once the membership user is saved to the database, the database will have the following tables
listoftables
All tables would seem familiar as they are used by Universal Providers for membership, roles, profile. The 2 new tables were created by Microsoft.AspNet.Membership.OpenAuth to integrate OAuth/OpenId information with membership system.
UsersOpenAuthAccounts: This holds the information on what providers can the user login by.eg if your app is configured to use Facebook, Google then the user can login via either of them and this information will be stored here
UsersOpenAuthData: This table integrates the OAuth/Openid login to the membership system.
Following image shows how OAuth/OpenId login information is wired to membership system.
usersdata
The membershipusername is the username in the Users table.At this stage since you have the users table populated you can create roles and add/remove these users from roles and thus achieve OAuth/OpenId integration with Roles as well
This entire sample is posted on my github repository(https://github.com/rustd/SocialLoginASPNET)
Feel free to download it and give it a try

What the default templates demonstrate more than this

To view the default templates incase you do not have VS 2012, you can browse them at the following github repro https://github.com/rustd/ASPNETTemplates
  • How to protect against XSRF attacks
  • Associate a local username/password with OAuth/OpenID account
  • Register with more than one OpenID/OAuth provider
I hope this would help in integration OAuth/OpenId easily into your application when you are not starting with the templates

Wednesday, August 28, 2013

5 Tips to Improve Your C# Code



Tip 1: StringBuilder consumes less memory than String

In my previous article I have shown how slow string is in a scenario of long concatenation operations. And here we will see a memory allocation graph of String and StringBuilder. Let me show that in action. The following is my code to do same operation with both a string and a StringBuilder.
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Diagnostics;using System.IO;using System.Net;using System.Net.NetworkInformation;using System.Threading;using System.Globalization;using System.Data.SqlClient;namespace Test1
{
    public class
Test1    {
        string Name ;
        public void Process()
        {
            Name = Name + "A";
        }
    }
    public class
Test2    {
        StringBuilder sb = new StringBuilder();
        public void Process()
        {
            sb.Append("A");
        }
    }
    class
Program    {
        static void Main(string[] args)
        {
            Test1 t = new Test1();
            t.Process();
            Test2 t1 = new Test2();
            t1.Process();
        }
    }
}


And here is the memory allocation graph from execution of the code.

image1.gif

Here from the main function we are calling the two functions Process(); though they both have the same name they belong to different classes and Test1.Process is handling string data whereas Test2.Process() is handling string builder data. And in the allocation graph we can see the String handling function consumes 94% resource of the Main () function whereas Process() in the Test2 class that deals with StringBuilder only consumes .21 % of the resources of the Main() function.

So, in a single line the conclusion is "Always use StringBuilder when you want to concatenate strings many times".

Tip 2: If possible use a static function

Yes, if possible try to implement a static function because static objects (both function and data) does not belong to any object of a particular class. It's common to all. So if you do not create an object then there is no question of memory consumption. In the following I am showing one example of a static function and static class. And have a look at the IL code.
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Diagnostics;using System.IO;using System.Net;using System.Net.NetworkInformation;using System.Threading;using System.Globalization;using System.Data.SqlClient;namespace Test1
{
    public static class
mySclass    {
        public static void Print()
        {
            Console.Write("Hello");
        }
    }
    public class
myNclass    {
        public static void Print()
        {
            Console.Write("Hello");
        }
    }
    class
Program    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 1000; i++)
            {
                mySclass.Print();
                myNclass.Print();
            }
        }
    }
}
The IL code is in the left hand side and in the right hand the top few memory consuming classes, taken by the CLR profiler. I cannot show the full screenshot of the CLR profiler due to space consumption. But believe me (Ha..Ha) there is no memory allocation of a static class or function.

image2.gif

So, in a single line the conclusion is "If possible try to create a static function and invoke with the class name rather than invoking the general function by object name".

Tip 3: String format VS String concatenation

In the first point I was showing how a string consumes more resources than a StringBuilder. In this point I will compare formatted output with string concatenation. In the first function I am using a format specification to print formatted output (basically I am concatenating a string). And in another function I am using the (+) operator to concatenate a string, as in the following:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Diagnostics;using System.IO;using System.Net;using System.Net.NetworkInformation;using System.Threading;using System.Globalization;using System.Data.SqlClient;namespace Test1
{
    class
Test    {
        public void Format()
        {
            int a = 100;
            Console.WriteLine("{0}AND{1}", a, a);
        }
        public void Concatination()
        {
            int a = 100;
            Console.WriteLine(a + "AND" +a );
        }
    }
    class
Program    {
        static void Main(string[] args)
        {
            Test t = new Test();
            t.Format();
            t.Concatination();
            Console.ReadLine();
        }
    }
}
And in memory allocation we will see:

image3.gif

That function that was printing a string using format is consuming 57 % of the resources and the function that simply concatenates two strings consumes 30 % resources of the main function. So we can clearly see if we use string concatenation rather than output formatting we can save our system resources.

Tip 4: Which class consumes maximum resources in an empty program?

First of all this point does not recommend any best practice technique. I just want to show that if we run one empty program (with just a Main() function in it) then how much memory is allocated? The following is my very simple program.
using System;using System.Collections.Generic;using System.Linq;using System.Text;
namespace
Test1
{
    class
Program    {
        static void Main(string[] args)
        {
        }
    }

}
Yes, I did not write anything in this program. Let's look at the memory map.

image4.gif

Here I am showing top six resource-consuming classes relevant to the scenario of when we run an empty program. It's clearly visible that the String class is taking the most resources (25 % of the whole). Now for a question. In a program that we never use a string, why does the string class consume the most resources? If we look at the call graph of this program then we will see in the main function many internal functions are being called and most of them are taking an argument as a string and to generate those arguments the CLR is usually using the String class. If you have different opinion please use comment box as in the following.

Tip 5: Implement a using block to manage memory

It's a best practice to always implement a using block to manage resources. And practically we can prove that a using block consumes less memory than without a using block statement. We know that if we implement a using block out code size might be larger because the using block internally creates a try catch in IL code but once it is implemented in IL code during runtime it efficiently handles system memory. To demonstrate this I have written a simple program as in the following.
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Diagnostics;using System.IO;using System.Net;using System.Net.NetworkInformation;using System.Threading;using System.Globalization;using System.Data.SqlClient;namespace Test1
{
    class
Test    {
        public void Test1()
        {
             StreamWriter wr = new StreamWriter(@"D:\text.txt");
        }
        public void Test2()
        {
             using (StreamWriter wr = new StreamWriter(@"D:\abc.txt"))
             {
             }
        }
    }
    class
Program    {
        static void Main(string[] args)
        {
            Test t = new Test();
            t.Test1();
            t.Test2();
        }
    }
}

And in the output section I have combined three output screens.

image5.gif

In the allocation graph we see that the using block is consuming less resources than without the using block because if we implement a using block, the program can manage memory efficiently.