Beginning of the year I posted an article on how you can create backend pages in the open source ASP.NET CMS Umbraco (http://blog.bartdemeyer.be/2013/01/using-mvc-backend-pages-in-umbraco-4-11-1). At the end of the post I published a little TODO list:
Due to a very busy work schedule I didn’t had the time to look into this list. In the mean while version 6 was released by the Umbraco core team.
Last week I received the question if I had already found a solution for the first item on the todo list: blocking access to the backend controller for non authenticated users.
Between the search for Easter eggs together with my son, backing pancakes and nothing interesting on the TV this evening I found the time to implement the feature.
Reminder: the problem
A small reminder of the problem we are facing. We’ve created a MVC controller to access from the Umbraco backend to perform our own business logic like shown in the image below.
We used the implementation if the Umbraco’s Surface Controller that will create a MVC area. If we know the structure of the URL to this area – controller – action we can access the page without logging in the Umbraco backend.
This is off course a security risk we have to solve. We don’t want non authenticated users to be able to access our business logic.
Using the Authorization attribute
In ASP.NET MVC access to certain controllers or individual actions is managed by using the Authorization annotation attribute. You can use the default attribute where you are able to filter request based on specific users or specific user roles.
But you can off course inherit from the default attribute and implement your own authorization attribute.
Create the UmbracoAuthorizeAttribute
Add a folder ‘Helpers’ in the UmbracoMVCDemo.BackEnd project. In that folder create a new class ‘UmbracoAuthorizeAttribute’. Add the public keyword to the class implementation and we shall inherit from the System.Web.MVC.AuthorizeAttribute.
Implementing your own authorization login can be done by overriding two methods from the base class: AuthorizeCore(HttpContextBase httpContext) and OnAuthorization(AuthorizationContext filterContext).
In AuthorizeCore(HttpContextBase httpContext) we will connect to the Umbraco backend to check if the user is authenticated or not.
I’ll first check if the httpContext contains any value, if not we’ll throw an exception. After that I’ll use a method from the Umbraco BasePage: ValidateUserContextID. This method will return true if the user is authenticated and false if not. With that result we’ll set a class variable we can use in the implementation of the OnAuthorization method.
In this implementation we’ll first execute the base class implementation before we check the failedAuthentication class variable. If the authentication in the failedAuthentication failed we’ll send the user to the login page using the FormsAuthentication class.
Adding authorization to our controller
It’s not enough to create the attribute, we still have to tell our controller to use the authentications we’ve implemented. Open up the DemoAdminSurfaceController class we created in the previous post and add the UmbracoAuthorize attribute (line 4).
I’ve opened up another browser and accessed the same action again. (keep in mind that we make use of the default FormsAuthentication that will use a session cookie. Therefor will a new tab in the same browser not give the desired effect). Because we’re not authenticated we get redirected to the login page.
You’ll see the url we entered in the ReturnUrl parameter. If we now enter our credentials we’ll get redirected to the Umbraco back end. Although the ReturnUrl is filled out we’ll not be redirected to the correct page. We still have to click on our demo Section and demo node.
I’ve had to alter the default web.config file to be correctly redirected to the login page. I’m not sure this needs to be done if you have a fresh installation, I’ll add it here to avoid bad redirections.