Skip to content

Getting Started :: Advanced Mvc Example (or .. the recommended Real World example)

PureKrome edited this page Nov 24, 2012 · 3 revisions

ASP.NET Advanced MVC Example

This is a slightly more advanced way to use the library because it shows how you can provide some state value to protect your site from Cross-Site Scripting.

If I was going to use this package library, then this would be the way I would incorporate it into my project. Why? Because this sample includes a random state value for XSS prevention.

Step 1 - Create some applications/account with your provider

Step 2 - Setup the providers.

A good place to do this is with Dependency Injection. Lets use StructureMap to do this :)

// Define a Registry.
public class AuthenticationRegistry : Registry
{
    public AuthenticationRegistry(IAuthenticationProvider facebookProvider,
                                  IAuthenticationProvider googleProvider,
                                  IAuthenticationProvider twitterProvider)
    {
        var authenticationService = new AuthenticationService();

        if (facebookProvider != null)
        {
            authenticationService.AddProvider(facebookProvider);
        }

        if (googleProvider != null)
        {
            authenticationService.AddProvider(googleProvider);
        }

        if (twitterProvider != null)
        {
            authenticationService.AddProvider(twitterProvider);
        }

        For<IAuthenticationService>()
            .Use(authenticationService)
            .Named("Authentication Service.");
    }
}

// Set up the IoC.
public static class IoC
{
    public static IContainer Initialize()
    {
        ObjectFactory.Initialize(x =>
                                    {
                                        var authenticationRegistry = new AuthenticationRegistry(
                                            new FacebookProvider(ConfigurationManager.AppSettings["FacebookAppId"],
                                                                ConfigurationManager.AppSettings["FacebookAppSecret"],
                                                                new Uri(ConfigurationManager.AppSettings["FacebookRedirectUri"])),
                                            new GoogleProvider(ConfigurationManager.AppSettings["GoogleConsumerKey"],
                                                            ConfigurationManager.AppSettings["GoogleConsumerSecret"],
                                                            new Uri(ConfigurationManager.AppSettings["GoogleConsumerRedirectUri"])),
                                            new TwitterProvider(ConfigurationManager.AppSettings["TwitterConsumerKey"],
                                                                ConfigurationManager.AppSettings["TwitterConsumerSecret"],
                                                                new Uri(ConfigurationManager.AppSettings["TwitterConsumerRedirectUri"]))
                                            );
                                        x.AddRegistry(authenticationRegistry);
                                    });
        return ObjectFactory.Container;
    }
}

// Finally, define a Controller ...
private readonly IAuthenticationService _authenticationService;

public HomeController(IAuthenticationService authenticationService)
{
    Condition.Requires(authenticationService).IsNotNull();

    _authenticationService = authenticationService;
}

Step 3 - Create a View which has the buttons/images/whatever.

This is some sample Razor code which shows a few images which are clickable.

<div id="container">
    <fieldset title="Login">
        <legend>Login:</legend>
        <a href="/Home/RedirectToAuthenticate?providerKey=Twitter"><img src="/Content/twitter_32.png"/></a>
        <a href="/Home/RedirectToAuthenticate?providerKey=Facebook"><img src="/Content/facebook_32.png" /></a>
        <a href="/Home/RedirectToFacebookMobile"><img src="/Content/facebook_mobile_32.png" /></a>
        <a href="/Home/RedirectToAuthenticate?providerKey=Google"><img src="/Content/google_32.png"/></a>
    </fieldset>
</div>

Step 4 - Redirect the client to an Authentication Provider (eg. Facebook, etc).

// Session Key.
private const string SessionStateKey = "SomeKey";

public RedirectResult RedirectToAuthenticate(string providerKey)
{
    // Which provider are we after?
    var settings = AuthenticationServiceSettingsFactory.GetAuthenticateServiceSettings(providerKey);

    // We need to remember the state for some XSS protection.
    Session[SessionStateKey] = Guid.NewGuid();
    settings.State = Session[SessionStateKey].ToString();

    // Grab the Uri we need redirect to.
    var uri = _authenticationService.RedirectToAuthenticationProvider(settings);

    // Redirect!
    return Redirect(uri.AbsoluteUri);
}

Step 5 - Handle the callback from the Authentication Provider. (eg. Facebook, etc).

public class AuthenticateCallbackViewModel
{
    public IAuthenticatedClient AuthenticatedClient { get; set; }
    public Exception Exception { get; set; }
}

public ActionResult AuthenticateCallback(string providerKey)
{
    if (string.IsNullOrEmpty(providerKey))
    {
        throw new ArgumentNullException("providerKey");
    }

    var model = new AuthenticateCallbackViewModel();
    try
    {
        // Retrieve the state for the XSS check.
        var state = Session[SessionStateKey] == null ? null : Session[SessionStateKey].ToString();
                
        // Complete the authentication process by retrieving the UserInformation from the provider.
        model.AuthenticatedClient = _authenticationService.CheckCallback(providerKey, Request.Params, state);

        // Clean up after ourselves like a nice little boy/girl/monster we are.
        Session.Remove(SessionStateKey);
    }
    catch (Exception exception)
    {
        model.Exception = exception;
    }

    // TODO: Now do whatever you want, with the retrieved User Information.
    //       EG. save this user to a DB.

    return View(model);
}