Click here to Skip to main content
16,016,882 members
Articles / Web Development / ASP.NET

OpenID With Forms Authentication

Rate me:
Please Sign up or sign in to vote.
4.96/5 (72 votes)
13 Dec 2010CPOL14 min read 377.6K   5.5K   168   84
Shows how to use OpenID with ASP.NET MVC Forms Authentication.

Introduction

As some of you may know from reading some of my past articles/blogs, I am not really a web man, but I had an idea a while back to create a tool that had to be web based, so I have been busy constructing this ASP.NET MVC web site in my spare time.

It is still ongoing, but one area that the web site needed was login/authentication, which is a pretty usual requirement on web sites. In fact, ASP.NET has long supplied Forms Authentication for this purpose (as well as other options). Thing is, I did not really want to store username/passwords in my database; then I read about this protocol called OpenID, which is a protocol that numerous web sites adhere to already. And if you have an OpenID compliant login, my site could allow its users to use those credentials directly with the OpenID compliant web site validating them. They basically handle the login/authentication process and redirect back to the original calling site (my site).

This may sound quite nuts, but it is quite probable that you yourself are already in possession of an OpenID login, as there are many OpenID compliant web sites out there. So it seemed to make sense to allow users to simply use their existing login credentials rather than to ask them to create even more credentials for my site.

This is all well and good, so what is this article all about? Quite simple really, this article will demonstrate how to use OpenID with Forms Authentication (to store the authentication cookie) within an ASP.NET MVC web site.

I should mention that this demo apps web site is not the prettiest of web sites, as I have literally applied no styling to it what so ever; I intentionally left it without trying to muddy the water so to speak. So please be aware that it is not going to win any beauty contests at all.

A Brief Discussion About OpenID

OpenID is an open standard that describes how users can be authenticated in a decentralized manner, obviating the need for services to provide their own ad hoc systems and allowing users to consolidate their digital identities.

The OpenID protocol does not rely on a central authority to authenticate a user's identity. Moreover, neither services nor the OpenID standard may mandate a specific means by which to authenticate users, allowing for approaches ranging from the common (such as passwords) to the novel (such as smart cards or biometrics).

The term OpenID may also refer to an ID as specified in the OpenID standard; these IDs take the form of a unique URL, and are managed by some 'OpenID provider' that handles authentication.

OpenID authentication is now used and provided by several large websites. Providers include AOL, BBC, Facebook, Google, IBM, MySpace, Orange, PayPal, VeriSign, LiveJournal, Yandex, Ustream, and Yahoo!

Using OpenID

A basic glossary of the terms used with OpenID:

  • End-user
  • The entity that wants to assert a particular identity.

  • Identifier or OpenID
  • The URL or XRI chosen by the end-user to name the end-user's identity.

  • Identity provider or OpenID provider
  • A service that specializes in registering OpenID URLs or XRIs and providing OpenID authentication (and possibly other identity services). Note that the OpenID specifications use the term "OpenID provider" or "OP". See also: List of OpenID providers.

  • Relying party
  • The site that wants to verify the end-user's identifier; other terms include "service provider" or the now obsolete "consumer".

  • User-agent
  • The program (such as a browser) used by the end-user to access an OpenID provider or a relying party.

Logging in

The end-user interacts with a relying party (such as a website) that provides a means by which to specify an OpenID for the purposes of authentication; an end-user typically has previously registered an OpenID (e.g., alice.openid.example.org) with an OpenID provider (e.g., openid.example.org).

The relying party typically transforms the OpenID into a canonical URL form (e.g., http://alice.openid.example.org/).

  • With OpenID 1.0, the relying party then requests the HTML resource identified by the URL and reads an HTML link tag to discover the OpenID provider's URL (e.g., http://openid.example.org/openid-auth.php). The relying party also discovers whether to use a delegated identity (see below).
  • With OpenID 2.0, the client discovers the OpenID provider URL by requesting the XRDS document (also called the Yadis document) with the content type application/xrds+xml; this document may be available at the target URL, and is always available for a target XRI.

There are two modes in which the relying party may communicate with the OpenID provider:

  • checkid_immediate, in which the relying party requests that the OpenID provider not interact with the end-user. All communication is relayed through the end-user's user-agent without explicitly notifying the end-user.
  • checkid_setup, in which the end-user communicates with the OpenID provider via the same user-agent used to access the relying party.

The checkid_setup mode is more popular on the Web; also, the checkid_immediate mode can fall back to the checkid_setup mode if the operation cannot be automated.

First, the relying party and the OpenID provider (optionally) establish a shared secret, referenced by an associate handle, which the relying party then stores. If using the checkid_setup mode, the relying party redirects the user's user-agent to the OpenID provider so the end-user can authenticate directly with the OpenID provider.

The method of authentication may vary, but typically, an OpenID provider prompts the end-user for a password or an InfoCard, and then asks whether the end-user trusts the relying party to receive the necessary identity details.

If the end-user declines the OpenID provider's request to trust the relying party, then the user-agent is redirected to the relying party with a message indicating that authentication was rejected; the relying party in turn refuses to authenticate the end-user.

If the end-user accepts the OpenID provider's request to trust the relying party, then the user-agent is redirected to the relying party along with the end-user's credentials. That relying party must then confirm that the credentials really came from the OpenID provider. If the relying party and OpenID provider had previously established a shared secret, then the relying party can validate the identity of the OpenID provider by comparing its copy of the shared secret against the one received along with the end-user's credentials; such a relying party is called stateful because it stores the shared secret between sessions. On the contrary, a stateless or dumb relying party must make one more background request (check_authentication) to ensure that the data indeed came from the OpenID provider.

After the OpenID has been verified, authentication is considered successful, and the end-user is considered logged in to the relying party under the identity specified by the given OpenID (e.g. alice.openid.example.org). The relying party typically then stores the end-user's OpenID along with the end-user's other session information.

If an OpenID provider uses strong authentication, OpenID can be used for secure transactions such as banking and e-commerce.

http://en.wikipedia.org/wiki/OpenID: Up on date 09/12/2010.

The Demo App

As I said at the beginning, the demo app is an ASP MVC web site that shows how to use OpenID along with Forms Authentication to store the authentication cookie.

This is what is looks like from a structural point of view:

Image 1

It can be seen that it follows the standard ASP MVC project structure, and the only other thing of real note there is that there are several Views, but only Site.aspx requires authorization to occur before it can be viewed.

What the Demo App is Trying to Achieve

What I wanted for my site was to be able to use OpenID, and I also wanted an OpenID provider to handle the actual logging in part, you know where the username and password are actually typed in. I did not want to have to mess with those at all. OpenID does also allow for you to let users enter their OpenID username and password on your site, and then validate these against an OpenID provider, but that is not what I wanted; rather, I wanted to redirect to an OpenID provider to let the user log in and then be told, yes that user is valid, here is their login token, which I could then store for later.

This may not suit your purposes, in which case you should probably look at alternative solutions to this one.

Showcasing the Demo App

When we launch the demo code, in Index.aspx (the ASP.NET MVC default HomeController.Index action ensures we end up with the Index.aspx view), we will see the following. This page does not require authorization of any sorts.

Image 2

What it does have is a link to a page (Site.aspx) that does require authorization before it can be viewed; when this link is clicked, we get something like this shown:

Image 3

There are a couple of things to note there, such as:

  1. The browser's address bar shows a query string which includes a ReturnUrl which is set to ReturnUrl=/Site/Data, which just happens to be the controller/action URL of the page that we tried to load that required authorization before it could be viewed. This ReturnUrl query string parameter is a standard feature of Forms Authentication, which is what we will eventually use to store just the Authentication cookie.
  2. There are quite a few image buttons that can be clicked. Each of these images represents an OpenID compliant site that you could use to login with. For example, I have a Google account, so I may choose to use my Google credentials. I should point out that I got the bulk of the content for the Logon.aspx page from a blog somewhere, but I can not recall where from, so apologies for not mentioning the source directly in this article.

If I proceed to use my Google account by clicking on the Google image, the current browser session will be navigated to Google, where I can enter my normal login credentials, as shown below:

Image 4

Once I have entered my usual Google (OpenID compliant) credentials, I will then be returned back to my previous page that I was on before I went off to the OpenID compliant web site to allow me to login, this obviously being Google in my case.

This is shown below after I have logged in using my Google credentials:

Image 5

You may be able see from this that the URL is not the original page that I wanted to view, not Site/Data, and not the login page. This is what the code in this article is all about; it shows you how to work with logging in to an OpenID compliant web site and to also use Forms Authentication to manage the Authentication cookie. In the example above, we basically did this:

  1. Loads a page that did not require any authentication (HomeController -> Index action -> Index.aspx).
  2. From there, we clicked a link to a page that required authentication (SiteController -> Data action -> Site.aspx). This immediately realised we were not authenticated yet, due to the lack of a Forms Authentication cookie, and redirected the browser session to the Login.aspx page (managed by the AccountController).
  3. From the Login.aspx page, we have a ReturnUrl (which is set to ReturnUrl=/Site/Data) to the original page that we attempted to view that needed the user to be authenticated before we could return to it.
  4. Next, we chose an OpenID provider to use; we are then redirected to the OpenID provider web site, where we log in.
  5. If the login process is successful, we are directed back to the original page that the user wanted to view (that's the ReturnUrl which Forms Authentication provides for us), that was not possible until the user was authenticated. This is achieved using a Forms Authentication cookie along with an ASP.NET MVC attribute, which we will discuss in the next section.

So How Does It All Work

Before I start to explain this, let me just say that my code relies on a third party DLL called "DotNetOpenAuth.dll" which is freely available at: http://www.dotnetopenauth.net/, where there are many .NET based demo examples and, of course, the DotNetOpenAuth.dll itself.

Specifying That a Page Needs Authorization Before It Can Be Viewed

This is perhaps the simplest part of the supplied demo code. Luckily for us, ASP.NET MVC comes with the very hand AuthoriseAttribute, that can literally be applied to your controllers that will restrict access of callers to the controllers actions unless they are authenticated. Which in our case means, we have logged in and have a Forms Authentication cookie stored in the session.

This is what the demo code's controller looks like that requires authorization to occur before the user can view the results of calling any of the actions:

C#
using System.Web.Mvc;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.RelyingParty;

namespace DotNetOpenIdTest.Controllers
{
    [HandleError]
    [Authorize]
    public class SiteController : Controller
    {
        public ActionResult Data()
        {
            return View("Site");
        }
    }
}

Login Page

The login page is where all the OpenID providers are shown, and where the user can click one of them to be redirected to the OpenID provider's web site. As I say, I got the bulk of this page from somewhere, but just can't seem to remember where, so if you think you know where it came from, let me know. Anyway, the login page's View looks like the following:

XML
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>OpenId Demo</title>
    <link rel="stylesheet" type="text/css" 
           media="screen" href="../../Content/openid.css" />
    <script type="text/javascript" src="../../Scripts/jquery-1.4.2.min.js"></script>
    <script type="text/javascript" src="../../Scripts/jquery.openid.js"></script>
    <script type="text/javascript">
        $(function () { $("form.openid:eq(0)").openid(); });
    </script>
</head>
<body>
    <div>
        <h2>
            Logon Using OpenId</h2>
        <p>
            <%=ViewData["message"]%></p>
        <form class="openid" method="post" action="/Account/Logon">
        <div>
            <ul class="providers">
                <li class="openid" title="OpenID">
                    <img src="../../Content/images/openidW.png" alt="icon" />
                    <span><strong>http://{your-openid-url}</strong></span></li>
                <li class="direct" title="Google">
                    <img src="../../Content/images/googleW.png" alt="icon" />
                    <span>https://www.google.com/accounts/o8/id</span></li>
                <li class="direct" title="Yahoo">
                    <img src="../../Content/images/yahooW.png" alt="icon" />
                    <span>http://yahoo.com/</span></li>
                <li class="username" title="AOL screen name">
                    <img src="../../Content/images/aolW.png" alt="icon" />
                    <span>http://openid.aol.com/<strong>username</strong></span></li>
                <li class="username" title="MyOpenID user name">
                    <img src="../../Content/images/myopenid.png" alt="icon" />
                        <span>http://<strong>username</strong>.myopenid.com/</span></li>
                <li class="username" title="Flickr user name">
                    <img src="../../Content/images/flickr.png" alt="icon" />
                        <span>http://flickr.com/<strong>username</strong>/</span></li>
                <li class="username" title="Technorati user name">
                    <img src="../../Content/images/technorati.png" alt="icon" />
                        <span>http://technorati.com/people/technorati/
                            <strong>username</strong>/</span></li>
                <li class="username" title="Wordpress blog name">
                    <img src="../../Content/images/wordpress.png" alt="icon" />
                        <span>http://<strong>username</strong>.wordpress.com</span></li>
                <li class="username" title="Blogger blog name">
                    <img src="../../Content/images/blogger.png" alt="icon" />
                        <span>http://<strong>username</strong>.blogspot.com/</span></li>
                <li class="username" title="LiveJournal blog name">
                    <img src="../../Content/images/livejournal.png" alt="icon" />
                        <span>http://<strong>username</strong>.livejournal.com</span></li>
                <li class="username" title="ClaimID user name">
                    <img src="../../Content/images/claimid.png" alt="icon" />
                        <span>http://claimid.com/<strong>username</strong></span></li>
                <li class="username" title="Vidoop user name">
                    <img src="../../Content/images/vidoop.png" alt="icon" />
                        <span>http://<strong>username</strong>.myvidoop.com/</span></li>
                <li class="username" title="Verisign user name">
                    <img src="../../Content/images/verisign.png" alt="icon" />
                     <span>http://<strong>username</strong>.pip.verisignlabs.com/</span>
                     </li>
            </ul>
        </div>
        <fieldset>
            <label for="openid_username">
                Enter your <span>Provider user name</span></label>
            <div>
                <span></span>
                <input type="text" name="openid_username" /><span></span>
                <input type="submit" value="Login" /></div>
        </fieldset>
        <fieldset>
            <label for="openid_identifier">
                Enter your <a class="openid_logo" href="http://openid.net">OpenID</a></label>
            <div>
                <input type="text" name="openid_identifier" />
                <input type="submit" value="Login" /></div>
        </fieldset>
        </form>
    </div>
</body>
</html>

Where the following jQuery based JavaScript (jquery.openid.js) is wiring up the images to the AccountController's Logon action. The only really important thing that happens is that the page is submitted from the following JavaScript; all the real work happens in the AccountController's Logon action code.

JavaScript
//jQuery OpenID Plugin 1.1
//Copyright 2009 Jarrett Vance http://jvance.com/pages/jQueryOpenIdPlugin.xhtml
$.fn.openid = function() {
  var $this = $(this);
  var $usr = $this.find('input[name=openid_username]');
  var $id = $this.find('input[name=openid_identifier]');
  var $front = $this.find('div:has(input[name=openid_username])>span:eq(0)');
  var $end = $this.find('div:has(input[name=openid_username])>span:eq(1)');
  var $usrfs = $this.find('fieldset:has(input[name=openid_username])');
  var $idfs = $this.find('fieldset:has(input[name=openid_identifier])');

  var submitusr = function() {
    if ($usr.val().length < 1) {
      $usr.focus();
      return false;
    }
    $id.val($front.text() + $usr.val() + $end.text());
    return true;
  };

  var submitid = function() {
    if ($id.val().length < 1) {
      $id.focus();
      return false;
    }
    return true;

  };
  var direct = function() {
    var $li = $(this);
    $li.parent().find('li').removeClass('highlight');
    $li.addClass('highlight');
    $usrfs.fadeOut();
    $idfs.fadeOut();

    $this.unbind('submit').submit(function() {
      $id.val($this.find("li.highlight span").text());
    });
    $this.submit();
    return false;
  };

  var openid = function() {
    var $li = $(this);
    $li.parent().find('li').removeClass('highlight');
    $li.addClass('highlight');
    $usrfs.hide();
    $idfs.show();
    $id.focus();
    $this.unbind('submit').submit(submitid);
    return false;
  };

  var username = function() {
    var $li = $(this);
    $li.parent().find('li').removeClass('highlight');
    $li.addClass('highlight');
    $idfs.hide();
    $usrfs.show();
    $this.find('label[for=openid_username] span').text($li.attr("title"));
    $front.text($li.find("span").text().split("username")[0]);
    $end.text("").text($li.find("span").text().split("username")[1]);
    $id.focus();
    $this.unbind('submit').submit(submitusr);
    return false;
  };

  $this.find('li.direct').click(direct);
  $this.find('li.openid').click(openid);
  $this.find('li.username').click(username);
  $id.keypress(function(e) {
    if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
      return submitid();
    }
  });
  $usr.keypress(function(e) {
    if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
      return submitusr();
    }
  });
  $this.find('li span').hide();
  $this.find('li').css('line-height', 0).css('cursor', 'pointer');
  $this.find('li:eq(0)').click();
  return this;
};

Login Process

The login process is conducted in the AccountController, and works as follows:

  1. Page that needs authorization is requested.
  2. Redirected to GET AccountController Logon action, if the user is not authenticated.
  3. Logon view is shown, which has all the OpenID provider links on them, where the HTML form is set to POST to the AccountController POST Logon action.
  4. User picks an OpenID provider, and clicks it, which calls the JavaScript, which really just results in the OpenID provider string being stored and a POST request being made to the AccountController Logon action.
  5. The AccountControllers POST Logon action does two things:
    1. It adds on a ClaimRequest, where it asks the OpenID provider to include Email/FullName in the data that will be included with a successful response from the OpenID provider.
    2. Then redirects the OpenID provider web site (via magic of DotNetOpenAuth.dll), where the user enters their details.
  6. If the user enters valid credentials at the OpenID provider's web site, they are redirected to the default Logon action on AccountController (via magic of DotNetOpenAuth.dll), at which point, it will examine the result from the OpenID provider IAuthenticationResponse response, which is available by calling the OpenIdRelyingParty type's GetResponse() method. If the response is found to be AuthenticationStatus.Authenticated, the user is deemed validated, and then more details about the user can be requested from the OpenID provider's response, which is accomplished using response.GetUntrustedExtension<ClaimsResponse> / response.GetExtension<ClaimsResponse>, where ClaimsResponse is the response that matches the ClaimsResponse that we asked the OpenID provider to include in the AccountController's POST Logon action in Step 5. We can then use the ClaimsResponse to obtain the user's Email and FullName from the OpenID provider's ClaimsResponse, which is stored in a small data construct that I have created, that is called UserData, which looks like this:
  7. C#
    public class UserData
    {
        public string Email { get; set; }
        public string FullName { get; set; }
    
        public override string ToString()
        {
            return String.Format("{0}-{1}", Email, FullName);
        }
    }
  8. The last thing that happens is that there is a FormsAuthenticationTicket/HttpCookie created for the OpenID authenticated UserData object.

Here is all the code for AccountController:

C#
using System.Web.Mvc;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.RelyingParty;
using System.Web.Security;
using System.Linq;
using System;
using System.Text.RegularExpressions;
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using System.Web;

namespace DotNetOpenIdTest.Controllers
{
    /// <summary>
    /// Simple class that represents a OpenId validated user in the system
    /// </summary>
    public class UserData
    {
        public string Email { get; set; }
        public string FullName { get; set; }

        public override string ToString()
        {
            return String.Format("{0}-{1}", Email, FullName);
        }
    }

    /// <summary>
    /// Provides actions/methods for creating an OpenId request and how to 
    /// obtain information from a authenticated OpenId response, and also 
    /// has methods for creating a Forms Authentication Ticket
    /// </summary>
    public class AccountController : Controller
    {
        #region Actions
        /// <summary>
        /// Show default logon page, and also see if user is already authenticated. 
        /// If they are we can examine the IAuthenticationResponse to get the 
        /// user data from the OpenId provider
        /// </summary>
        /// <returns></returns>
        public ActionResult LogOn()
        {
            ViewData["message"] = "You are not logged in";

            OpenIdRelyingParty openid = new OpenIdRelyingParty();
            IAuthenticationResponse response = openid.GetResponse();

            //check for ReturnUrl, which we should have if we use forms 
            //authentication and [Authorise] on our controllers
            if (Request.Params["ReturnUrl"] != null)
                Session["ReturnUrl"] = Request.Params["ReturnUrl"];

            if (response != null && 
                response.Status == AuthenticationStatus.Authenticated)
            {
                var claimUntrusted = 
                    response.GetUntrustedExtension<ClaimsResponse>();
                var claim = response.GetExtension<ClaimsResponse>();

                UserData userData = null;

                if (claim != null)
                {
                    userData = new UserData();
                    userData.Email = claim.Email;
                    userData.FullName = claim.FullName;
                }

                //fallback to claim untrusted, as some OpenId providers may not
                //provide the trusted ClaimsResponse, so we have to fallback to 
                //trying the untrusted on
                if (claimUntrusted != null && userData == null)
                {
                    userData = new UserData();
                    userData.Email = claimUntrusted.Email;
                    userData.FullName = claimUntrusted.FullName;
                }
            
                //now store Forms Authorisation cookie 
                IssueAuthTicket(userData, true);

                //store ClaimedIdentifier it in Session 
                //(this would more than likely be something
                //you would store in a database I guess
                Session["ClaimedIdentifierMessage"] = response.ClaimedIdentifier;

                //If we have a ReturnUrl we MUST be using forms authentication, 
                //so redirect to the original ReturnUrl
                if (Session["ReturnUrl"] != null)
                {
                    string url = Session["ReturnUrl"].ToString();
                    return new RedirectResult(url);
                }
                //This should not happen if all
                //controllers have [Authorise] used on them
                else
                    throw new InvalidOperationException("There is no ReturnUrl");
            }
            return View("LogOn");
        }

        /// <summary>
        /// Logon post request, so redirect to OpenID
        /// provider and when they authenticate, 
        /// redirect back to orginal url which is the
        /// one that needed authenticating in the 1st place
        /// </summary>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult LogOn(string openid_identifier)
        {
            var openid = new OpenIdRelyingParty();


            IAuthenticationRequest request = 
              openid.CreateRequest(Identifier.Parse(openid_identifier));
            var fields = new ClaimsRequest();
            fields.Email = DemandLevel.Require;
            fields.FullName = DemandLevel.Require;
            request.AddExtension(fields);
            return request.RedirectingResponse.AsActionResult();
        }

        /// <summary>
        /// Logoff and clears forms authentication cookie
        /// </summary>
        /// <returns></returns>
        public ActionResult LogOff()
        {
            Session.RemoveAll();
            Session.Clear();
            Session.Abandon();
            Response.Cookies.Remove("AUTHCOOKIE"); 
            FormsAuthentication.SignOut();

            return View("LogOff");
        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Issue forms authentication ticket
        /// for authenticated user, and store the cookie
        /// </summary>
        private void IssueAuthTicket(UserData userData, bool rememberMe)
        {
            FormsAuthenticationTicket ticket = 
                new FormsAuthenticationTicket(1, userData.Email,
                    DateTime.Now, DateTime.Now.AddDays(10),
                    rememberMe, userData.ToString());

            string ticketString = FormsAuthentication.Encrypt(ticket);
            HttpCookie cookie = 
              new HttpCookie(FormsAuthentication.FormsCookieName, ticketString);
            if (rememberMe)
                cookie.Expires = DateTime.Now.AddDays(10);

            HttpContext.Response.Cookies.Add(cookie);
        }
        #endregion
    }
}

Web.Config

I found that I had to add a dotNetOpenAuth config section in Web.Config for the OpenId.Dll to work correctly with some providers (Google). Oh, I am also showing that Forms Authentication is enabled too.

XML
<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="dotNetOpenAuth" 
      type="DotNetOpenAuth.Configuration.DotNetOpenAuthSection" 
      requirePermission="false" 
      allowLocation="true"/>
  </configSections>

    .......
    .......
    .......
    .......
    .......


  <!-- The following OPTIONAL behavior allows 
            RPs to use SREG only, but be compatible
            with OPs that use Attribute Exchange (in various formats). -->
  <dotNetOpenAuth>
    <openid>
      <relyingParty>
        <behaviors>

          <add type="DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform, 
                     DotNetOpenAuth" />
        </behaviors>
      </relyingParty>
    </openid>
  </dotNetOpenAuth>

  <!-- Allow Forms Authentication, 
             and set Login url (AccountController/LogOn action) -->
  <authentication mode="Forms">
    <forms loginUrl="~/Account/LogOn" timeout="2880"/>
  </authentication>
    .......
    .......
    .......
    .......
</configuration>

That's It

Anyway, that is all I really wanted to say. I know web development is not my normal arena, so I have more than likely made some school boy errors. If that is the case, please tell me as I am just about to put this into my private out of hours ASP MVC project. So any of you advanced/seasoned ASP MVC devs reading this, see anything wrong, please let me know.

Likewise, if you liked the article, it would be nice to hear about that, by way of a comment/vote.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)

- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence

Both of these at Sussex University UK.

Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2016
  • Codeproject MVP 2016
  • Microsoft C# MVP 2015
  • Codeproject MVP 2015
  • Microsoft C# MVP 2014
  • Codeproject MVP 2014
  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Comments and Discussions

 
QuestionException throwing in using google login Pin
Upniwesh16-Mar-16 8:17
Upniwesh16-Mar-16 8:17 
GeneralMy vote of 5 Pin
Humayun Kabir Mamun3-Sep-13 0:25
Humayun Kabir Mamun3-Sep-13 0:25 
QuestionYour project is incompatible in Visual Sudio 2012. VS can not even convert it Pin
Shashwat Tripathi18-Aug-13 10:14
Shashwat Tripathi18-Aug-13 10:14 
AnswerRe: Your project is incompatible in Visual Sudio 2012. VS can not even convert it Pin
Sacha Barber18-Aug-13 11:17
Sacha Barber18-Aug-13 11:17 
GeneralRe: Your project is incompatible in Visual Sudio 2012. VS can not even convert it Pin
Shashwat Tripathi12-Oct-13 7:51
Shashwat Tripathi12-Oct-13 7:51 
GeneralRe: Your project is incompatible in Visual Sudio 2012. VS can not even convert it Pin
Sacha Barber12-Oct-13 10:48
Sacha Barber12-Oct-13 10:48 
QuestionProblem in the Authentication Pin
Julio Piza3-May-13 11:43
Julio Piza3-May-13 11:43 
QuestionBuild is failed without error in error list Pin
Hussain naqvi10-Nov-12 7:20
Hussain naqvi10-Nov-12 7:20 
AnswerRe: Build is failed without error in error list Pin
Sacha Barber13-Nov-12 13:35
Sacha Barber13-Nov-12 13:35 
GeneralMy vote of 5 Pin
Vitaly Tomilov10-Jun-12 6:55
Vitaly Tomilov10-Jun-12 6:55 
Question.Net 3.5 Version? Pin
Marc Uberstein18-Apr-12 3:09
Marc Uberstein18-Apr-12 3:09 
AnswerRe: .Net 3.5 Version? Pin
Sacha Barber18-Apr-12 3:27
Sacha Barber18-Apr-12 3:27 
QuestionThanks Sacha !!! Pin
GregFoote19-Nov-11 9:28
GregFoote19-Nov-11 9:28 
AnswerRe: Thanks Sacha !!! Pin
Sacha Barber20-Nov-11 7:59
Sacha Barber20-Nov-11 7:59 
GeneralMy vote of 5 Pin
Bryian Tan15-Mar-11 3:50
professionalBryian Tan15-Mar-11 3:50 
GeneralMy vote of 5 Pin
Mohammad Said Hefny12-Mar-11 5:41
Mohammad Said Hefny12-Mar-11 5:41 
GeneralRe: My vote of 5 Pin
Sacha Barber20-Nov-11 7:59
Sacha Barber20-Nov-11 7:59 
GeneralMy vote of 5 Pin
GPUToaster™26-Feb-11 17:15
GPUToaster™26-Feb-11 17:15 
GeneralMy vote of 5 Pin
dev4ever15-Feb-11 22:51
dev4ever15-Feb-11 22:51 
GeneralRe: My vote of 5 Pin
Sacha Barber20-Nov-11 8:00
Sacha Barber20-Nov-11 8:00 
GeneralFacebook as OpenID Provider Pin
janpub14-Feb-11 6:57
janpub14-Feb-11 6:57 
GeneralRe: Facebook as OpenID Provider Pin
Sacha Barber14-Feb-11 22:48
Sacha Barber14-Feb-11 22:48 
GeneralRe: Facebook as OpenID Provider Pin
dev4ever15-Feb-11 22:51
dev4ever15-Feb-11 22:51 
GeneralRe: Facebook as OpenID Provider Pin
Sacha Barber15-Feb-11 23:05
Sacha Barber15-Feb-11 23:05 
GeneralRe: Facebook as OpenID Provider Pin
GPUToaster™26-Feb-11 17:17
GPUToaster™26-Feb-11 17:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.