.NET Option 1

Add PixelPin for a simple and secure way to access your .Net site

Create a New Project (Optional)

Please note that we provide two sample projects that have the PixelPin plugin already integrated. These can be used as a starting point or alternatively to compare to your own projects for troubleshooting. There is an MVC Example and a Web Forms Example.

If you are starting from scratch, use File->New->Project. Do NOT choose "Web Site", which is mainly designed for static content and requires a lot more code before it works as an application.

In the New Project dialog, choose either a Web Forms or an MVC project. Both are compatible with the OAuth2 libraries. You can choose C# or VB.Net but the examples below show C# only and will need to be modified for VB accordingly.

Get NuGet package manager

To add the required PixelPin plugin (DotNetOpenAuth client for PixelPin and ASP.Net Membership), the best way is to use the NuGet package manager. Please check to find out whether you already have NuGet integrated into Visual Studio by right-clicking the references folder of your project and looking for the menu option to "Manage NuGet Packages..." or otherwise, use Tools->Extensions and Updates to search for and install it.

Install the PixelPin NuGet Package

Using NuGet (right-click references and choose Manage NuGet Packages), Search for "PixelPin" and add the DotNetOpenAuth client for PixelPin and ASP.Net Membership.

Adding via NuGet can often add too many additional libraries. You don’t, for instance, need relying party, OAuth (as opposed to OAuth2) or openid dlls.

Create a PixelPin developer account

You can get a PixelPin developer account from the Accounts section after logging in. After registering the account, make sure you write down the client code and secret on the final page. See below in the MVC or webforms section for the default .Net redirect URIs for MVC and web forms. Note, you can register the base URI without the querystring which is ignored when the OAuth2 request is checked. This is because the querystring usually has variables in it.

New .Net Projects

If you have a new project (or a recent one that has not been heavily edited), Visual Studio will have created you a file under App_Start called AuthConfig.cs/.vb where you can configure the settings for your PixelPin developer account.

Existing .Net Projects (optional)

If you are applying PixelPin to an existing site, you will need to add the following code to your project. Note, if you get stuck, the easiest thing to do is to create a new project in the same style (MVC/Web Forms) as your existing project and use the new code as a reference for the changes you need to make. The changes will also depend on whether you already have external providers configured for Single-Sign-On, in which case you should just be able to download the PixelPin provider and configure it.

  1. There are many possible combinations of existing projects, therefore some of these pieces of code might already exist and therefore do not need to be added.

  2. Add a new file into a folder called App_Start in the root of your project. The file can be called what you like, but the MS convention is AuthConfig.cs. Note, you should use the folder name App_Start because it is automatically protected by IIS on the web server.

  3. In this new class, add a method of the type

    public static void RegisterAuth()

    (The name is up to you.)

  4. In this new method, add the following code

    OAuthWebSecurity.RegisterClient(new PixelPinOAuth2Provider("<client code>", "<secret>"), "PixelPin", null);

    You will need usings for COM.PixelPin.FederationClient and Microsoft.Web.WebPages.OAuth.

  5. Call this new method from Application_Start() in Global.asax.cs

  6. Ensure you have the NuGet package mentioned above which includes the required DLLs for PixelPin and DotNetOpenAuth

MVC web applications

  1. Note the redirect url for mvc projects to use in your developer account is in the (default) form of

    http://yoursite.com/Account/ExternalLoginCallback
  2. If using MVC, you will need an action link to "login with PixelPin" this should call a controller action, which in turn calls

  3. return new ExternalLoginResult("PixelPin", Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));

  4. ExternalLoginResult is a helper class like this:

    internal class ExternalLoginResult : ActionResult
    {
        public ExternalLoginResult(string provider, string returnUrl)
        {
            Provider = provider;
            ReturnUrl = returnUrl;
        }
    
        public string Provider { get; private set; }
        public string ReturnUrl { get; private set; }
                        
        public override void ExecuteResult(ControllerContext context)
        {
            OAuthWebSecurity.RequestAuthentication(Provider, ReturnUrl);
        }
    }
    
    		
  5. ExternalLoginCallback is a callback action which will do the remainder of the OAuth2 handshake via DotNetOpenAuth. It looks like this:

    [AllowAnonymous]
    public ActionResult ExternalLoginCallback(string returnUrl)
    {
        AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new 		{ ReturnUrl = returnUrl }));
        if (!result.IsSuccessful)
        {
            return RedirectToAction("ExternalLoginFailure");
        }
                        
        if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false))
        {
            return RedirectToLocal(returnUrl);      // User already has local account
        }
                        
        if (User.Identity.IsAuthenticated)
        {
            // If the current user is logged in add the new account
            OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, User.Identity.Name);
            return RedirectToLocal(returnUrl);
        }
        else
        {
            // User is new, ask for their desired membership name
            string loginData = OAuthWebSecurity.SerializeProviderUserId(result.Provider, result.ProviderUserId);
            ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName;
            ViewBag.ReturnUrl = returnUrl;
            return View("ExternalLoginConfirmation", new RegisterExternalLoginModel { UserName = result.UserName, ExternalLoginData = loginData });
        }
    }
    
    
  6. ExternalLoginFailure and RedirectToLocal are generic error actions and the main redirect respectively. ExternalLoginConfirmation is an action designed to let the user select a local username and confirm their new account. It looks like this:

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult ExternalLoginConfirmation(RegisterExternalLoginModel model, string returnUrl)
    {
        string providerUserId = null;
    
        if (User.Identity.IsAuthenticated || !OAuthWebSecurity.TryDeserializeProviderUserId(model.ExternalLoginData, out provider, out providerUserId))
            {
                return RedirectToAction("Manage");
            }
                                
            if (ModelState.IsValid)
            {
                // Insert a new user into the database
                using (UsersContext db = new UsersContext())
                {
                    UserProfile user = db.UserProfiles.FirstOrDefault(u => u.UserName.ToLower() == model.UserName.ToLower());
                    // Check if user already exists
                    if (user == null)
                        {
                            // Insert name into the profile table
                            db.UserProfiles.Add(new UserProfile { UserName = model.UserName });
                            db.SaveChanges();
                                
                            OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
                            OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false);
    
                            return RedirectToLocal(returnUrl);
                        }
                    else
                        {
                            ModelState.AddModelError("UserName", "User name already exists. Please enter a different user name.");
                        }
               	}
            }
    
            ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(provider).DisplayName;
            ViewBag.ReturnUrl = returnUrl;
            return View(model);
    }
    
    

Web Forms Applications

The code included in a default asp web forms project contains DotNetOpenAuth and makes use of a User Control (.ascx) to allow re-use across pages. This step is optional, however it is also acceptable to embed the relevant forms code into your login page without the user control.

  1. Note the redirect url for web forms projects to use in your developer account is in the (default) form of http://yoursite.com/Account/RegisterExternalLogin.aspx

    Using a user control

    1. The default web forms application has this user control under the Account directory, if this exists then you just need to use it on a web form like this:

      <uc:OpenAuthProviders runat="server" ID="OpenAuthLogin" />

      after registering it at the top of the form like this:

      <%@ Register Src="~/Account/OpenAuthProviders.ascx" TagPrefix="uc" TagName="OpenAuthProviders" %>
    2. After adding the control, the code behind the page (in Page_Load) needs to set the ReturnUrl to that being passed in the querystring:

      OpenAuthLogin.ReturnUrl = Request.QueryString["ReturnUrl"];
    3. If your project does not have the OpenAuthProviders.ascx user control under /Account (and you want to use it), create a new Web Forms project and copy the ascx and cs code files for ~/Account/OpenAuthProviders.ascx into your project from that.

  2. Calling DotNetOpenAuth directly

    1. The code that would normally be in the user control is as below. You can use this as-is or modify it to suit your needs (for instance using image buttons instead of text buttons):

      <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>
              <div class="message-info">
                  <p>There are no external authentication services configured.</p>
              </div>
          </EmptyDataTemplate>
      </asp:ListView>
    2. Wire up the SelectMethod property to the code behind (the example above uses "GetProviderNames")

      public IEnumerable<ProviderDetails> GetProviderNames()
      {
          return OpenAuth.AuthenticationClients.GetAll();
      }
      
    3. Add the following code to your login page code-behind into your existing Page_Load event handler:

      protected void Page_Load(object sender, EventArgs e)
      {
          if (IsPostBack)
          {
              var provider = Request.Form["provider"];
              if (provider == null)
              {
                  return;
              }
      
              var redirectUrl = "~/Account/RegisterExternalLogin";
              if (!String.IsNullOrEmpty(ReturnUrl))
              {
                  var resolvedReturnUrl = ResolveUrl(ReturnUrl);
                  redirectUrl += "?ReturnUrl=" + HttpUtility.UrlEncode(resolvedReturnUrl);
              }                        
      
              OpenAuth.RequestAuthentication(provider, redirectUrl);
          }
      }
    NOTE: that in both cases you will need the page RegisterExternalLogin in the account folder which you can obtain from a new web forms project