ASP.NET MVC Authentication Using Facebook’s C# SDK

In this sample application, ASP.NET MVC 4 RC and .NET/C# 4.0 versions were used.

Facebook Application

Create first a Facebook application on http://developers.facebook.com/apps, click the “Create New App” and follow the instructions. Take note of App ID and App Secret values for this will be needed later on.

Nuget

Facebook C# SDK is installed using Nuget. If you currently have Nuget, you should download and install it. If you already have one installed, please make sure that it is the latest version.

ASP.NET MVC 4 Website

On your visual studio 2010, create a new ASP.NET MVC website. Install Facebook C# SDK by going to Tools -> Library Package Manager -> Package Manager Console. This will open a window. On the window, type “Install-Package Facebook”. This may take a while depending on your connection. After installing, it will show you some information about the SDK and its version. The version used in this sample is “Facebook 6.0.20″. This can also be done by right clicking the projects References folder and select “Manage Nuget Packages…”. Search for the Facebook package and install it.

Facebook App Configuration

Now that C# Facebook SDK is installed and the website was set up, the site URL on the Facebook app should be modified. This must match the URL you are using on your development machine. This URL should be, http://localhost:##### where ##### is the port number on local machine.

Authenticating Site Users with Facebook

On the ASP.NET MVC website template, when a user attempts to log in, it will load a log on page where the user will input the username and password. On this sample application, when the user clicks on the login link, it will redirect them to Facebook for authentication. This will load the Facebook login page and after successfully authenticating, the user will be asked to authorize your app. After authorization, Facebook will redirect back to your site with a token  that denotes the authenticated Facebook Session.

This Session Token is needed to request for an Access Token from Facebook’s Graph API Service. After obtaining the Access Token, you can query the some of the users information like UserId or UserName by using the Graph API.

How it was done

1. Create a Controller Action that Redirects to Facebook

The action should redirect to Facebook’s URL: https://graph.facebook.com/oauth/authorize. There are 3 necessary query strings that must be included with this URL:

  1. client_id: your Facebook’s Application ID.
  2. redirect_uri: URI that Facebook will redirect to after successful authentication. This must be prefixed with the Site URL that has been provided on Facebook and is case sensitive. The redirect_uri will be a controller action in our ASP.NET MVC site.
  3. type: user_agent or web_server. We will be using web_server for we are not authenticating asynchronously via javascript.

This is the code of our controller that handles the redirect to Facebook:

[AllowAnonymous]
public ActionResult FacebookLogin()
{
    return new RedirectResult("https://graph.facebook.com/oauth/authorize? type=web_server& client_id=492401047441790& redirect_uri=http://localhost:56898/account/FacebookLoginOK");
}

We have the AllowAnonymous attribute added so the user can access this controller even if the it is not yet authenticated.

On our _LoginPartial.cshtml partial page under the views/shared folder we will modify the login link to:

<li>@Html.ActionLink("Log in", "FacebookLogin", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li>

When clicking the login link on the upper right side of the main page, this will go to the controller which in turn will redirect to Facebook. Facebook’s login page will be shown and after successfully authenticating, will be redirected to the URI specified on redirect_uri on controller code above.

2. Handle the Redirect from Facebook

We will now create a controller as mentioned on the redirect_uri above to handle the redirect.

Our main goal is to have the Facebook user’s username or userid. To do that, we will use the Facebook C# SDK’s FacebookClientClass with our access token.

Here is the code.


[AllowAnonymous]
public ActionResult FacebookLoginOK(string code)
{
    //parameter code is the session token
    if (!string.IsNullOrEmpty(code))
    {
        var appId = "492401047441790";
        var appSecret = "8a16ff46000eb9725704487877741655";

        //URL to access for the access token
        string url = "https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&client_secret={2}&code={3}";

        //redirectUri must be the same URI that initiates the initial authentication call. in this case,
        // this controller action
        string redirectUri = "http://localhost:56898/account/FacebookLoginOK";

        //Create and perform a request using the URI
        WebRequest request = WebRequest.Create(string.Format(url, appId, redirectUri, appSecret, code));

        //Read the response as UTF-8 and parse out the access token.
        //Note that the result has access token and expires parameter.
        WebResponse response = request.GetResponse();
        Stream stream = response.GetResponseStream();
        Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
        StreamReader streamReader = new StreamReader(stream, encode);
        string result = streamReader.ReadToEnd();
        result = result.Remove(result.IndexOf("&expires"));
        string accessToken = result.Replace("access_token=", "");
        streamReader.Close();
        response.Close();

        //Instantiate a new facebookClient from the C# SDK with the accessToken as parameter.
        var client = new FacebookClient(accessToken);

        //This will return a JSON object with similar format like:
        //{
            // id: "10000000",
            // name: "Blah Blah",
            // first_name: "Blah",
            // last_name: "Blah",
            // link: "https://www.facebook.com/blahblah",
            // username: "blah",
            // gender: "male",
            // locale: "en_US"
        //}

        //Uses a dynamic variable to handle the JSON result
        dynamic me = client.Get("me");
        //Can now have the value from the dynamic expression
        string username = me.username;

        //Authenticate the user in your site.
        FormsAuthentication.SetAuthCookie(me.username, false);
     }

  return RedirectToAction("Index", "Home");
}

User is now authenticated and can now use any resource provided by  the Graph API in this link https://developers.facebook.com/docs/reference/api/.  All entities returned for the Graph Api are JSON objects so you can use dynamic data type like above.

I could not do this blog if I have not read http://amirrajan.net/Blog/asp-mvc-and-facebook-single-sign-on and http://csharpsdk.org/docs/web/getting-started. More powers to the authors!!!

Hashing Password using SHA512, SHA256, SHA1 and MD5

This is update to my previous post regarding hashing of passwords. Recent security articles have noted that most SHA1 and MD5 hashing algorithm is no longer safe anymore for there were instances that the hash has been broken. So it is advisable to have a stronger hashing algorithm, and it was recommended to have the SHA256 or the SHA512.

Here is my function to hash text depending on what algorithm is needed, be it MD5, SHA1, SHA256 or SHA512.

private string GetHash(string text, string passwordFormat = "SHA256")
        {
            HashAlgorithm _algorithm;
            switch (passwordFormat.ToUpper())
            {
                case "MD5":
                    _algorithm = MD5.Create();
                    break;
                case "SHA1":
                    _algorithm = SHA1.Create();
                    break;
                case "SHA256":
                    _algorithm = SHA256.Create();
                    break;
                case "SHA512":
                    _algorithm = SHA512.Create();
                    break;
                default:
                    throw new ArgumentException("Invalid password format.", "passwordFormat");
            }
            byte[] bytes = Encoding.UTF8.GetBytes(text);
            byte[] hash = _algorithm.ComputeHash(bytes);
            string hashString = string.Empty;
            foreach (byte x in hash)
            {
                hashString += String.Format("{0:x2}", x);
            }
            return hashString.ToUpperInvariant();
        }

The length of the hashed password considering we have a password(unencrypted) with 50 characters and a salt of 16 characters are as follows:

  1. MD5 : 33 characters
  2. SHA1: 41 characters
  3. SHA256: 64 characters
  4. SHA512: 128 characters

Hashing Password with Salt using MD5 or SHA1 in ASP.NET MVC

In today’s application, passwords should not be stored as clear text. It should be stored in an encrypted or hashed format. Between the two(hashed and encrypted) hashing is more secure for it uses a one way function and it is very difficult to retrieve the original string especially if a salt is applied to the hash before storing it. Even site or database administrators with access to the code or the data in the database will have difficulty in generating the original password from its hashed format.

Encryption however, is also secure but not as secure as the hashed format. Encryption is a two way function, meaning you can encrypt and decrypt the string using the key. In an application, in order to encrypt the password you need a key. The key is also used to decrypt the encrypted password. This key will most probably be stored somewhere in the application or on the database. So anyone who has access to the key can crack the password including the site admin and database administrators.

In ASP.NET MVC, password hashing can be done using FormsAuthentication.HashPasswordForStoringInConfigFile function which will take the password and a password format in which in can be “SHA1″ or “MD5″.

It would be more secure if a salt is applied to the password before storing. A way to do it is to generate a salt and concatenate the password and the salt before applying the hashing algorithm of choice. It is also advisable to have the salt as a random string.

To generate a random string, use the RNGCryptoServiceProvider.

public string GenerateSalt(int length)
{
    var rng = new RNGCryptoServiceProvider();
    var buffer = new byte[length];
    rng.GetBytes(buffer);
    return Convert.ToBase64String(buffer);
}

Now we can generate a hashed password using the function below

public virtual string CreatePasswordHash(string password, string saltkey, string passwordFormat = "SHA1")
{
    if (String.IsNullOrEmpty(passwordFormat))
        passwordFormat = "SHA1";
    string saltAndPassword = String.Concat(password, saltkey);
    string hashedPassword =
        FormsAuthentication.HashPasswordForStoringInConfigFile(
            saltAndPassword, passwordFormat);
    return hashedPassword;
}

And now thats it. the result of that function is a hash of the original password and can now be stored on the database.

How are your password being stored?

Project Euler Problem 10 F# Solution Using Sieve of Eratosthenes

Here is my F# solution to project Euler problem number 10. I am using Sieve of Eratosthenes in coming up the list of prime numbers.

This is not pure functional. I used recursive function to get the integer list of prime numbers. But i got an exception upon adding all the integer primes. It seems the integer type could not hold the values. So i did loop all the primes and put its sum on the BigInteger type.

Add a reference to System.Numerics.BigInteger before running the code. Its not fast. It took several minutes to get the list of primes. If you have suggestion to make this efficient, please feel free to drop comments.

let list = [2 .. 2000000]
let p = list.Head
let rec primes list p plist=
 let nplist = List.concat [plist; [p]]
 match List.tryFind (fun x -> x > p) list with
 | None -> nplist
 | Some value -> primes (list |> List.filter (fun x -> x > p && x % p <> 0)) value nplist

let primelist = primes list p []

let mutable sum = new System.Numerics.BigInteger(0)
for i in primelist do
 sum <- sum + new System.Numerics.BigInteger(i)

Project Euler Problem 20 F# Solution

Ive been trying to solve some of the problems in project euler using F# programming language. I know some of my code are kind of awkward and the way I solve the problem is not the best solution. Anyway it did solve some of it. Here is my F# solution for problem number 20.

Before you run the code below, add first the reference to System.Numerics. Feel free to comment if you wanna say something about the code or you can suggest improvements. I am still beginning to learn F# and I would appreciate any help.

let fact x:System.Numerics.BigInteger =

 let rec tailRecursiveFactorial x acc:System.Numerics.BigInteger =
 if x <= new System.Numerics.BigInteger(1) then
 acc
 else
 tailRecursiveFactorial (x - new System.Numerics.BigInteger(1)) (acc * x)
 tailRecursiveFactorial x (new System.Numerics.BigInteger(1))

let x = fact (new System.Numerics.BigInteger(100))
let digitsum = [for a in x.ToString().ToCharArray() -> ((int)(a.ToString()))] |> List.sum

Internationalization of .NET String Resources using Resgen.exe

Applications must be designed to accommodate users from various cultures. International systems should be able to handle different locale like en-US, en-PH, es-MX and others. In .NET there are many ways to do this and this will show how to make your application resources handle globalization.

Lets have an example, in an application, we wished to have a message saying “Username not found!”. But we also want that “Username not found!” will be shown like “¡Username no encontrado!” if our locale is es-MX (spanish-Mexico). (pardon me if the translation is wrong, babelfish.altavista.com did the translation).

Now lets add a default resources file. The application will be handling string resources only.

1. Create a resources.txt file.
2. On the file, put a resource key and value, “UserNameNotFound = Username not found!” without qoutes.
3. Open a visual studio command prompt and navigate to the root of your application directory.
4. The following command reads a text-based input file Resources.txt and writes a binary resources file named Resources.resources. It also generates a C# file named Resources.cs with a class named Resources that contains strongly-typed properties that match the resources that are referenced in the input file. The Resources class is contained within a namespace named ResourceManager.

>resgen Resources.txt /str:C#,ResourceManager,Resources,Resources.cs

4. Right click on the generated files, Resources.cs and Resources.resources and Include in project.

The resources generated by this is the default resource.

We can now access the file with the code:

Resources.UserNameNotFound <– this will return “Username not found!” as specified on our text file. The key in our textfile will be a static property in the generate resources class

Now we are done with the default resource.

We will now be doing the es-MX translation.

Lets build a satellite assembly for another culture.

In this sample we will use es-MX.

1. Create a folder named es-MX on the root folder of the project.
2. Under the folder, create another resource file named Resources.es-MX.txt. Note that the filename should be the same as the base language resource except that it has the culture info after the name and before the extension. Use the same key as our default resource but its value is translated to spanish(Mexico), “UserNameNotFound = ¡Username no encontrado!” again without the quotes.

3. Generate a .resources files with the command:

>resgen es-MX\Resources.es-MX.txt Resources.es-MX.resources

Assuming we are on the the root folder of the project.
The command above will generate a resource file (Resources.es-MX.resources) on the current directory from the input file in the es-MX directory.
4. Include the generated file (Resources.es-MX.resources) in the project.
5. We can view the translated text in our es-MX resources by:

CultureInfo ci = new CultureInfo("es-MX"); <– create a new culture info es-MX
Resources.Culture = ci; <– set the culture info of our Resource class to es-MX
Resources.UserNameNotFound <– This will return “¡Username no encontrado!” as specified on our es-MX resource.

Text files (txt) are handy than xml(resx) files if the one doing the translation does not belong to the development team. On a text file, you will just send the original/default resources and have it translated. After translation generate the resource and you are done.

And thats it. If you have some comments or suggestions, please feel free to leave it below.

PDF Page Counter Using F# and ITextSharp

The purpose of this sample program is to count the number of pages a PDF file have. This is written in F# and I used the ITextSharp library for counting the PDF Pages.

This solution has 2 projects, an F# library to handle the processing and a C# console application that uses the library and displays the filename and the number of pdf pages.

Before we begin with the code, the ITextSharp DLL must be downloaded first from here.

After having the the DLL, create an F# project and reference the ITextSharp DLL.

The flow of the program is as follows: From a given directory, count the number of pages on all the PDF files.

So on our F# code, we have to “open” (using in c#) the ITextSharp for the PDF processing and the System.IO for the directory information.

open System.IO
open iTextSharp.text

Next, we will create a function to count the number of pages of a given PDF and return a tuple of a string and int for its file name and its number of pages.

let internal Counter (file: string) = async {
    let pReader = new iTextSharp.text.pdf.PdfReader(file)
    return (file, pReader.NumberOfPages)
    }

So the function above named Counter will take a string parameter the file, and will return a tuple, the file and the number of pages. The async keyword here says that this function can be run in parallel.

So we now have our function to count the number of pages a PDF file have. I will now have the code to get all the files from a given directory.

type PDFReader (dir: string) =
    static member CountNumberOfPages(dir) =
        let di = new DirectoryInfo(dir)
        di.GetFiles()
        |> Seq.filter(fun f -&gt; f.FullName.EndsWith(".pdf"))
        |> Seq.map (fun f -&gt; Counter f.FullName)
        |> Async.Parallel
        |> Async.RunSynchronously

In the code above, I made a class named PDFReader with a constructor that takes a single string parameter. That class has a single static function named CountNumberOfPages that takes the directory where the PDF files are located.

The CountNumberOfPages function gets all the files from the directory with the code:

let di = new DirectoryInfo(dir)
di.GetFiles()

The GetFiles() function will return an Array/Sequence of all the files in the directory. But we dont know if all the files are all pdf so we have to filter it out.

|> Seq.filter(fun f -> f.FullName.EndsWith(".pdf"))

After knowing that the filtered list is now all PDF we will apply a function, the Counter function above, to each of the element of the sequence.

|> Seq.map (fun f -> Counter f.FullName)

This function will return a new Sequence with values from the application of the function Counter on the values of the former sequence. The new value is the pair of the filename and its number of pages.

Then we will run it in parallel.

|> Async.Parallel
|> Async.RunSynchronously

Our library is done.

module Module1

open System.IO
open iTextSharp.text

let internal Counter (file: string) = async {
    let pReader = new iTextSharp.text.pdf.PdfReader(file)
    return (file, pReader.NumberOfPages)
    }

type PDFReader (dir: string) =
    static member CountNumberOfPages(dir) =
        let di = new DirectoryInfo(dir)
        di.GetFiles()
        |> Seq.filter(fun f -> f.FullName.EndsWith(".pdf"))
        |> Seq.map (fun f -> Counter f.FullName)
        |> Async.Parallel
        |> Async.RunSynchronously

As you have observed, the library will execute in parallel, and the code to make it parallel is not obtrusive, meaning, the logic flow is the same, we did not create threads or pools to make it multi threaded.

We will now create a c# console application to use our library and try it. I will just put the code here, its self explanatory. Dont forget to reference the F# library on the C# console application.

class Program
{
    static void Main(string[] args)
    {
        string path = "C:\\TEMP";
        foreach (var tup in Module1.PDFReader.CountNumberOfPages(path))
        {
            Console.WriteLine("filename: {0} Num of pages: {1}", tup.Item1, tup.Item2.ToString());
        }
        Console.Read();
    }
}

Note: Readers are expected to be knowlegeable in C# and F# basics.

Follow

Get every new post delivered to your Inbox.