You’ve probably see on the wild on websites such as StackOverflow, but if you don’t know what it is, it is a single sign-on mechanism that allows user of your website to use his existing profile on an provider, such as Gmail, Yahoo, Wordpress, etc. so by providing this service on your website, you allow the user to login without gooing through all the hoops of creating and validating an account which is usable on a single website only.

The way it functions is that you are forwarded to the provider of your choice, authenticate with your existing account there, and from there you’ll be forwarded back to the website you originated the request from. An authentication token is also sent from the provider which uniquely identifies that user. Let’s see how we can add support to our ToBeSeen website.

To start, go grab latest version of -selector library which is a JS library that contains the look and feel similar to StackOverflow. Open the “LogOn.cshtml” file in you asp.net mvc project and change it to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@using (Html.BeginForm("Authenticate", "Account", FormMethod.Post, new { id = "_form" }))
{
<div>
<fieldset>
<legend> Provider</legend>

<div id="_choice">
<p>Please click your account provider:</p>
<div id="_btns"></div>
</div>
<div id="_input_area">
<input id="_provider" name="_provider" value="http://"/>
<input id="_submit" type="submit" value="Sign-In"/>
</div>
</fieldset>
</div>
}

Also you need to include the .css and .js files of “-selector” on your master page and then call the init function using jQuery:

1
2
3
4
5
6
7
8
9
<head>
<script src="@Url.Content("~/Scripts/jquery-1.4.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/-jquery.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/-jquery-en.js")" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
.init('_provider');
});
</head>

Now firing up your website and switching to /Account/LogOn you can see the nice user interface that allows you to login to a bunch of providers.

Open ID Provider

Now back to coding parts. To speak to providers, the best bet is to use DotNetOpenAuth library. Grab it and add the assembly named DotNetOpenAuth to your project. We need to create an action on AccountController named “Authenticate”, so create that as well. The authentication is a two part mechanism, first you create a request and call the provider and then when provider authenticates (or fails to do so) he will call you back on the same action method, and you can get the response and check if the status was success or not. It all boils down to this function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public virtual ActionResult Authenticate(string _provider)
{
var = new RelyingParty();
var response = .GetResponse();

if (response == null)
{
var request = .CreateRequest(_provider);
return request.RedirectingResponse.AsActionResult();
}

if (response.Status == AuthenticationStatus.Authenticated)
{
FormsService.SignIn(response.ClaimedIdentifier);
return RedirectToAction("Index", "Home");
}

ModelState.AddModelError("", "Authentication failed.");
return View("LogOn");
}

The providers can do more than just authentication. They can provide you profile information given they support sending the profile information you request. For this example, let’s just grab the user’s email address which we may later use to display on the master page, but mind you that specs. contain much more than just email address information.

Some prodivers do not disclose some part of their uses’s profile data.

To request profile information, which are called Claims, you need to add the information you need to the initial request.

1
2
var request = .CreateRequest(_provider);
request.AddExtension(new ClaimsRequest {Email = DemandLevel.Require});

and when processing the response, you can easily read the claims information:

1
2
var fetch = response.GetExtension<ClaimsResponse>();
FormsService.SignIn(fetch.Email);

Hope this clarifies how easy it is to plug into your existing web applications.