.NET Option 2

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

Use NuGet package manager

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

Choose your Login Page

You need to decide where you are going to action the login e.g. what page or control will be your login page. You can use any server control that can postback such as a LinkButton or normal Button. All this control needs to do is call an event handler, which needs to call the following:

IAuthorizationState authorization = pixelPinClient.ProcessUserAuthorization();
if (authorization == null)
{
    // Kick off authorization request
    pixelPinClient.RequestUserAuthorization(returnTo: new Uri("http://mysite.com/Account/RegisterExternalLogin.aspx"));
}
else
{
    // Already logged in
}

The Uri passed to the RequestUserAuthorization method is the page that PixelPin will return to with the result of the login. You will either need to create a new page for this or use an existing page that can handle the return values (see later). This must also match the return uri you specified when you created the PixelPin developer account otherwise attempting to login will produce a request error on the PixelPin web site.

It doesn’t matter where these pages are in your site, they do not have to be inside the Account folder, for example, as long as you pass the redirect uri into the RequestUserAuthorization method.

The PixelPinClient should be declared statically somewhere that can be accessed by multiple pages, such as in a class in app_code:

internal static readonly PixelPinDotNetOpenAuthClient pixelPinClient = new PixelPinDotNetOpenAuthClient
{
    ClientIdentifier = "B0XJ2Q6J8HS66E3U2QROJKDV3R6JZV",
    ClientCredentialApplicator = ClientCredentialApplicator.PostParameter("rujh8--*sa_on@=ohv.L!uxst"),
};

Handling the Return URL

If you want to handle a return url to allow the user to be redirected back to a protected page that sent them to the login page in the first place, you should pass this as part of the querystring on the return uri passed to PixelPin (NOT the querystring of the redirect itself). Encoded, therefore it might look something like:

https://login.pixelpin.co.uk/OAuth2/Flogin.aspx?redirecturi=http%3A%2F%2Fwww.mysite.com%2FAccount%2FExternalLoginCallback.aspx%3Freturnurl%3D%2FUser%2FDashboard.aspx&clientid=....

The querystring is not taken into account when the return url is validated by PixelPin so it is acceptable to have different querystrings for different scenarios.

Once RequestUserAuthorization is called, the browser will be redirected to the PixelPin login page and it should have passed the client id (in plain text), a return URL and a state parameter which prevents replay attacks. It will also include a response type which tells PixelPin to return an authorization code (this is the only type supported).

One of two things can now happen. The login can fail (or be cancelled) in which case, an error will be returned in the querystring to the return uri, otherwise a code parameter will be returned in the querystring. The presence of the code in the querystring tells your site that a login has been successful and that the rest of the handshake should follow in order for you to obtain the user’s details. It’s absence tells you that an error has occurred and it is up to you to decide how to handle this, perhaps displaying a simple message saying “login failed”. For example, you could have something like this in a file called RegisterExternalLogin:

protected void Page_Load()
{
    if (!IsPostBack)
    {
        var returnUrl = Request.QueryString["ReturnUrl"];
        if (!String.IsNullOrWhiteSpace(Request.QueryString["code"]))
        {
            // Success
            IAuthorizationState authorization = pixelPinClient.ProcessUserAuthorization();
            if (authorization == null)
            {
                // Go back to login page - this should not happen
            }
            else
            {
                // Get data for the user. Under the covers, this performs the remainder of the
                // OAuth2 handshake
                PixelPinGraph oauth2Graph = pixelPinClient.GetGraph(authorization);

                // Now we need to link this data to a local account, either existing or new
            }
        }
        else
        {
            // Error occurred logging in - do something useful and tell the user
        }
    }
}

The comments above show what needs to be done. Going back to the login page if the code is present but somehow the authorization could not be processed would be unusual (Can’t imagine why, except perhaps a mangled querystring?) Showing an error if a code is not returned is also fairly straight-forward. The OAuth2 docs on our developer site show what data is returned with the error and it can either be displayed directly or logged somewhere.

Linking the PixelPin account to a Local account

The tricky part is now to link the PixelPin account with a local account. If you use the built-in membership classes of Asp.net, this is all handled for you but in this case, you need to wire it in yourself and decide how to handle the following scenarios:

  1. A completely new user logs in (the email address you receive from PixelPin does not relate to a user in your database). You will need to create a new account, possibly capture more information that PixelPin provides and store that all in the local user accounts table preferably with the userid passed back from PixelPin so you can symbolically link the two accounts.

  2. Somebody logs in using PixelPin but they already have a local account with the same email address. Probably, you will simply symbolically link them and then log them in (since you have probably already captured any other info required).

  3. Somebody logs in with a PixelPin id that matches your local database but with a different email address i.e. they have updated their email address either on your site or at PixelPin (although this is currently not possible on the PixelPin site!). You must decide what you want to do. The cleanest way is to disconnect the original account and simply create a new one but if the account has important assets attached to it, you will need to decide how to present this to the user in an appropriate way (or not- just do it all automatically)

Note that most of these changes are required for all OAuth2 providers, not just PixelPin. Others are available via NuGet for Twitter, Google etc so most of this work only needs to happen once.

Adding Other Login Providers

If you added other providers like Facebook, Google, Twitter etc. there is one more thing you would need to do.

When you called the relevant flavour of RequestUserAuthorization, in the returnurl that you pass to it, you should add another querystring parameter, perhaps something like provider=pixelpin or provider=google etc.

You will need this so that when the login returns to your site via the return uri, you will know which of the clients to use to continue the handshake:

if ( Request.QueryString["provider"] == "pixelpin" )
{
pixelPinClient.ProcessUserAuthorization();
}
else if ( Request.QueryString["provider"] == "google" )
{
googleClient.ProcessUserAuthorization();
}