MVC – Getting User Roles From Multiple Sources (register and resolve arrays of dependencis using the fluent api)

In the last post I talked about encapsulating the authorisation and user credentials (i.e IPrincipal) logic in a separate, re-usable DLL (known as AuthServices).

Part 1 of that post discussed the DLL contents in detail. Part 2 focused upon using that DLL in an MVC application.

This post follows up on “Part 2” specifically adding a user’s roles to the UserData objet prior to serialisation, on-route to becoming the auth cookie.

The code sample that I gave for using the AuthServices DLL is repeated below:

_authenticationService.Authenticate(userNameString, password);
if (_authenticationService.Result.Authenticated)
{
       _currentUserData = _authenticationService.Result.CurrentUserData;
       _currentUserData.Roles = GetRolesForUser(userName);//THE SUBJECT OF THIS POST
       _cookieManager.CreateUserCookie(userName, _currentUserData);
}

This post explores in more detail what lies behind the GetRolesForUser(string userName) method and how this can utilise more than one provider of roles.

Why bother?

The organisation in which I work is big. We have thousands of staff and many thousands more students. Applications written for an organisation of this size usually need to access different sources of data to provide a user’s roles relevant to the specific application. In projects like this you can’t easily use the standard RoleProvider stuff in a config file.

The Answer – Multiple Role Providers

To implement multiple roles I inject (in an IOC stylee) into my login service the interface IRolesMgr. IRolesMgr exposes the following:

public interface IRolesMgr
    {
        List GetAllRolesForUser(string userName);
    }

The interesting part is in the constructor of the implementation.

public class RolesMgr: IRolesMgr
    {
        private IRoleMgrComponent[] _roleManagers;

        public RolesMgr(IRoleMgrComponent[] roleManagers)
        {
            _roleManagers = roleManagers;
        }

        public List GetAllRolesForUser(string userName)
        {
            List roles = new List();
            foreach (var mgr in _roleManagers)
            {
                roles.AddRange(mgr.GetRolesForUser(userName));
            }
        }
    }

As can be seen the constructor has a dependency on an array of IRoleMgrComponents each of which will contain the access logic needed to identify a user’s roles from a different source.
Each IRoleMgrComponent implements the following:

public interface IRoleMgrComponent
    {
        List GetRolesForUser(string userName);
    }

That’s all very good, but the trick is getting the IOC container, in this case, Castle Windsor, to instantiate the appropriate implementations of IRoleMgrComponent in the roleManagers array.

This is done in the Component Registrar class used to register components to Castle by using the “ServiceOveride” method (more details of this can be seen on Mike Hadlow’s post – which was the original inspiration for the castle registration code – thanks Mike!). In effect this allows you to register and resolve arrays of dependencis using the fluent api.

container.Register(
                Component.For()
                    .ImplementedBy()
                    .ServiceOverrides(
                        ServiceOverride.ForKey("roleManagers").Eq(
                            "HumsAuthDbRoleManager",
                            "StudentAuthRoleMgr"
                        )
                    ),
                AllTypes
                    .FromAssemblyNamed("ApplicationServices")
                    .BasedOn()
                        .WithService.FromInterface(typeof(IRoleMgrComponent))
                        .Configure(c => c.Named(c.Implementation.Name))
                );

Once you have overriden this specific component you can continue to register all the other components in that assembly in the normal way, say:

container.Register(
                AllTypes.Pick()
                .FromAssemblyNamed("ApplicationServices")
                .WithService.FirstInterface());

Conclusion

Implementing RolesMgr(IRoleMgrComponent[]) in conjunction with the AuthServices assembly talked about in the last post, means that for any given new project I will only have to write minimal code yet benefit from User Credential information that:
a) Has the execution logic encapsulated in an (extensible) AuthServices library
b) Can uitilise dependency injection to configure how where and how the roles data comes from in the credential information.

Creating a resusable Authorisation/ User Principal library for MVC projects

Having been using SharpArchitecture/ MVC for a number of recent projects, I’ve finally made the effort to extract some common service features into a separate reusable project (with unit tests of course!). This is very much inkeeping with DRY principles and should shorten the time to (re)-implement common processes in new projects.

The project – AuthUserServices provides several useful interface/implementations that can be used in any (MVC/ or Non-MVC) .NET project. It aint rocket science but provides a number of neat and unit tested resources around Authorisation and GenericPrinicpal.

Part 1 – The AuthServices DLL

The IAuthenticationService

This interface exposes two methods:

void Authenticate(string userName, string password)// Authenticates against a user directory
void FindUser(string userName)// Ascertains whether a user is contained in a user directory

And an AuthenticationResult propterty…

AuthenticationResult Result { get; }

… which is a struct containing result information supplied from “Authenticate” or “FindUser”.

The current implementation(s) of this interface are for LDAP and CAS. Our MVC projects implement dependency injection using Castle Windsor. It is therefore fairly trivial to choose the IAutheniticationService implementation in the component register (specific examples to follow).

AuthenticationResult

The AuthenticationResult struct exposes the following properties:

public bool Authenticated {get;}// bool describing whether a user is authenticated
public string ConnectionMessage {get;}// any message that comes from connecting with/ or communicating with a user directory
public string SearchString {get;} // the string used to search the user directory, i.e. the username
public IUserData UserData {get;}// An object containing user details gleaned from searching the user directory

IUserData

IUserData exposes the following properties:

string Email { get; }
string FName { get; }
string SomeOtherProperty { get; }
List Roles { get; set; }
string SName { get; }
string ToString();

In the AuthServices project there is only one implementation of this interface (cunningly) called UserData. I implemented this as an interface so that it is possible to provide other implementations in the future. For example the

ToString()

implementation is used to serialise the object for use in a cookie. It is possible that a developer may with to implement a different serialisation algorithm.

UserData

UserData object data is built from a directory search or authentication attempt. It has two constuctors.
The first is used to create the UserData from properties gleaned from the user directory

public UserData(string email, string fName, string sName, string someOtherProperty)

The second is used to deserialise a userDataString contained in the UserData property in an auth cookie (in effect the reverse of the

ToString()

implementation.

public UserData(string userDataString)

The UserData class encapsulates the logic involved in managing user data across the Authorisation –> Cookie serialisation/deserialisation –> Building the User Principal process.

ICurrentUserCookieMgr

The ICurrentUserCookieMgr interface doesn’t expose a huge amount of functionality.

void CreateUserCookie(string userName, IUserData userData);
bool HttpOnly { get; set; }
void RemoveUserCookie();

The current implementation implements FormsAuthentication. It is the only part of the service that doesn’t really have adequate unit tests due to it’s (necessary) reliance upon HttpContext and the Response therein. Still the implemenation encapsulates this functionaly and can easily be stubbed/ mocked in application unit tests.

IHumsPrincipal

The final item of the service is the IHumsPrincipal interface. This exposes the the UserData and UserName properties as well as the IIdentity and property and IsInRole method available in the standard MS IPrincipal interface.

IIdentity Identity { get; }
bool IsInRole(string role);
IUserData UserData { get; }
string UserName { get; }

Part 2 – Example Uses in an (MVC) app

Using AuthServices in the Authorisation logic of an application

I use the AuthServices implementation in a LoginService within an ApplicationServices project.
The LoginService has the following private members

private ICurrentUserMgr _userManager;
private IAuthenticationService _authenticationService;
private ICurrentUserCookieMgr _cookieManager;

You can then manage the whole cookie building/ roles setting process with only a few lines of code

_authenticationService.Authenticate(userNameString, password);
if (_authenticationService.Result.Authenticated)
{
       _currentUserData = _authenticationService.Result.CurrentUserData;
       _currentUserData.Roles = GetRolesForUser(userName);//Some logic to determine the roles (SEE NEXT BLOG POST ABOUT THIS)
       _cookieManager.CreateUserCookie(userName, _currentUserData);
}

Accessing User Info

Post authentication, developeres can use the implementations of IHumsPrincipal and IUserData in the Application_OnAuthenticateRequest in the Global.asax file of their apps to expose UserData properties to the application. e.g.

FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
string userId = id.Ticket.Name;
IUserData uData = new UserData(id.Ticket.UserData);
HttpContext.Current.User = new HumsPrincipal(id.Name, uData, id);

You could then expose the IHumsPrincipal members in the application (such as a controller or application by casting the CurrentPrincipal to the IHumsPrincipal as follows:

IHumsPrincipal p = Thread.CurrentPrincipal as IHumsPrincipal;

Better still would be to encapsulate this cast behind an “ICurrentUserManager” interface to remove the dependency within controller/app service methods upon the Thread and therefore make such methods easy to unit test. For example:

public class CurrentUserMgr: ICurrentUserMgr
    {
        IHumsPrincipal _principal
        {
            get
            {
                try
                {
                     return Thread.CurrentPrincipal as HumsPrincipal;
                }
                catch
                {
                    return null;
                }
            }
        }

        public CurrentUserMgr()
        {

        }

        public bool IsStudent()
        {
            if (_principal == null)
                return false;
            else return _principal.IsInRole("student");
        }

        public bool IsSysAdmin()
        {
            if (_principal == null)
                return false;
            else return _principal.IsInRole("sysadmin");
        }

        public bool IsLoggedIn()
        {
            try
            {
                return _principal.Identity.IsAuthenticated;
            }
            catch
            {
                return false;
            }
        }
    }

Castle Wiring of AuthServices DLL in the Component Register

Finally, in an MVC, project you have to register AuthServices library in an MVC project.

container.Register(
     AllTypes.Pick()
     .FromAssemblyNamed("Humanities.Reusable.Components.AuthUserServices")
     .WithService.FirstInterface());

Automating JavaScript Testing with QUnit

I haven’t had a time to look at this yet, but keen to get some more testing goodness and order into my JS/JQuery.

Automating JavaScript Testing with QUnit

Error Handling with Elmah

I’ve been looking at error handling lately and come across ELMAH.

So far so good – it is easy to configure and has a variety of options for storing errors.

It also allows for enterprise wide reporting whereby different applications use the same error store.

Ace!

You can also use Elmah for error  signalling so that you can log errors that arise not from unhandled exceptions but from managed circumstances (such as a web service time out or some such).

Finally you can also get ELMAH to play nice with MVC’s HandleError attribute,  so that it logs all controller errors (which would be bypassed if decorated with [HandleError] as it only deals automatically with UNhandled exceptions. Details of how to do this are contained in this StackOverflow post (incidentally apparently SO use a fork of ELMAH n’all!)

(ADDED: This was useful for deployment to IIS 7)

ADDED by Andrew: Also, the applicationName attribute of the errorLog tag is very useful when you have more than one application logging to the same database, e.g.:

<errorLog type="Elmah.SqlErrorLog, Elmah" applicationName="My App Name"
  connectionString="..." providerName="System.Data.SqlClient" />

Increasing the security of AJAX requests from the browser

Just a quickie.

I’ve a situation where I need to use AJAX to get a list of items for a particular user.

The for the request is in a hidden field (i.e. fully publicly viewable) in the DOM

e.g. http://www.example.com/users/alexhardman/items

The problem with using the username here is that it is human readable which makes it very easy to hack by changing on or more of the characters.

To increase the securing I’ve added a guid row to my user table which will be used to retrieve users.

e.g. http://www.example.com/items/for/7275670d-f06d-4be2-b260-4c8e094ead6c

This makes it infinitely more difficult to hack the url and return information for a user other than the one given in the url.

e.g.

Unit testing MVC Controllers with Model Validation

If you use ModelState.isValid in your controller classes then you will run into problems during unit testing as it will always return true as Model Validation occurs during the Request pipeline, which isn’t the route followed during testing

To overcome I’ve implemented a static controller extension “CallWithModelValidation” as seen below:

public static class ControllerExtensions
    {
        //Enforeces model validation during testing. This is required because model binding doesn't occur in 
        //during testing which means that ModelState.IsValid is always true
        //Taken from
        //http://blog.overridethis.com/blog/post/2010/07/08/MVC2-Validation-and-Testing-e28093-Refactored.aspx
        public static ActionResult CallWithModelValidation<C, R, T>(this C controller
            , Func<C, R> action
            , T model)
            where C : Controller
            where R : ActionResult
            where T : class{
            DataAnnotationsModelValidatorProvider provider = new DataAnnotationsModelValidatorProvider();

            IEnumerable<ModelMetadata> metadata = ModelMetadataProviders
                .Current
                .GetMetadataForProperties(model, typeof(T));
            foreach (ModelMetadata modelMetadata in metadata) 
            {
                IEnumerable<ModelValidator> validators = provider
                    .GetValidators(modelMetadata, new ControllerContext());
                
                foreach (ModelValidator validator in validators) 
                {
                    IEnumerable<ModelValidationResult> results = validator.Validate(model);
                    foreach (ModelValidationResult result in results)
                        controller.ModelState.AddModelError(modelMetadata.PropertyName, result.Message);
                }
            }
            return action(controller);
        }
    }

This can then be called in your controller test by doing the following (where in the case below “AddSupplier” is the controller method under test):

_testController.CallWithModelValidation(m => m.AddSupplier(viewModel), viewModel).AssertViewRendered().ForView("CreateSupplier");

Word Wrap in CSS

The following does ‘proper’ word wrapping in all the browsers I tested it in (i.e. excluding IE6)

.wordwrap {
    white-space: pre-wrap; /* css-3 */
    white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
    white-space: -pre-wrap; /* Opera 4-6 */
    white-space: -o-pre-wrap; /* Opera 7 */
    word-wrap: break-word; /* Internet Explorer 5.5+ */ 
}