Development Framework for Sitecore MVC

Source code for this framework is available on GitHub

It’s been 3 year I have been working on Sitecore Mvc (6.6 & 7.2) and had seen some of the bad and best enterprise framework laid out for Sitecore development. With Sitecore it is really important to structure the solution correctly to facilitate development team to design a scalable solution and code without worrying about another part of the application. It is also important to develop individual components without any dependency on the functional or non functional part of the code.

This tempted me to write an abstract framework or layout the basic building block of the application which are required for any Sitecore Mvc development. I have found other frameworks available e.g Sitecore Mvc Contrib or Sample Sitecore Mvc but I haven’t used them so far.

It is not possible to cover all the feature in this post and it may require a series of post to cover it. Following are the feature included so far. I will turn them in links once I have the relevant post out.

  1. Pluggable Mvc Areas Implementation
  2. Form Post in Siteocre MVC
  3. Exception Handling
  4. Dependency Injection – Container agnostic
  5. Asynchronous Logging – Framework agnostic
  6. Integration with Claims Identity
  7. Glass Mapper Implementation
  8. Unit Testing

Architecture
This Project is designed using Sitecore 7.2 and Mvc 5.1 and here is how it looks like from solution alignment point of view.

Sitecore Solution Architecture

The key consideration here is to un-touch the Sitecore Host project and code outside of it using pluggable module, on build just deploy the required files in host project’s respective directories and run the application. This open up the idea of deploying individual component as separate module in Sitecore via xcopy, nuget package or any other deployment mechanism. It helps in environment where multiple teams are working independently.

Exception handling is designed to handle the application error via HttpModule and Mvc specific one with Sitecore’s Exception Processor. The important part of it is that it avoids the redirect and render the error page content along with correct error status code. Framework keeps the error handling simple but it doesn’t stop if there is a need for richer experience. I wrote about it long back here , this can be still applied to present more customized solution.

Dependency Injection is achieved via a Framework IoC class but it internally rely on a container which could be any container available, either Unity, Windsor or any other. This allows less dependency on the DI container and build application specific code. The current application uses Unity as sample implementation.

Logging implementation is asynchronous and it uses BackgroundWorker class to process log to consuming framework. The current implementation uses a simple file to write the log. It can be enhanced to use the new .net based async/await support or AsyncCollection for cleaner implementation.

The other major feature it supports is ClaimsIdentity over the existing IIdentity implementation for Claims based access. It allows access to User attributes in the runtime for more fine grain control over the user properties and access. This can further be extended to support Federation authentication within the application.

I haven’t added the full glass mapper example and unit testing yet but that’s in-progress.

How to setup

This solution is consist of 3 main module, 1) Framework 2) Modules (Mvc Areas) 3)Host Project

Framework is build with 4 projects

  1. Infrastructure- Infrastructure project contains dependency injection and Logging functionality.
  2. Sitecore Extension- This project contains extensions for Sitecore areas & error handling pipelines, support for ClaimsIdentity and some helper classes.
  3. Web Extension- Currently it has helper and extension classes to support Form Post.
  4. Setup- This project contains unity based DI implementation, file logger and application bootstrap to wire-up all project together without making any modification in Host project.

Module is nothing but collection of Mvc projects with area registration classes to support pluggable application development and it can be deployed to Host project as package.

Host is a Sitecore project and it works are integration point for Framework and pluggable Mvc modules.

Steps

  1. Download the source code for this article from GitHub and open the solution in Visual Studio 2013, you will notice it has all the projects available but host project doesn’t have much except, App_Config/Include/Framework for config file required by Framework, empty Areas folder, script and content folder for jquery and bootstrap css files.
  2. Download the Sitecore 7.2 from SDN.
  3. Copy below files/folder from Sitecore7.2 downloaded zip file to Host project directory.
    1. App_Config folder
    2. bin folder
    3. Layouts folder
    4. Sitecore folder
    5. Sitecore Modules folder
    6. Sitecore_files folder
    7. Temp folder
    8. Data folder with license file
    9. Upload folder
    10. xsl folder
    11. Default.aspx
    12. default.css
    13. default.js
    14. global.asax
    15. Web.config
    16. webedit.css

      Once everything is ready, build the solution and it should generate the required assembly inside the Host project’s bin folder to run the application.

      Disclaimer
      This solution is still in development and not been used on any production environment. I am trying my best to test out all the aspect of framework but if you are planning to use this framework, let me know and I will try to help you set it up, just shoot me an email.

      Any feedback, drop in the comment section or email me.

Posted in Framework, MVC, Security, Sitecore | Tagged , , , , | 9 Comments

GlassMapper with Unity as DI Container

Default GlassMapper demo application uses CastleWindsor as DI container to resolve the dependencies in the runtime. This is also documented as part of the 1st tutorials on glass mapper site. There is another implementation with SimpleInjector but in situation if you are using Unity as DI Container in your application this will not work you need to either use unity with CastleWindsor or change the implementation. I did see a question related to Unity on the Glass Mapper google group forum.

Glass Mapper’s CastleWindsor DI implementation has 4 component.

  1. DependencyResolver
  2. GlassMapperSc
  3. GlassMapperScCustom
  4. IObjectConstruction Pipeline
  5. SitecoreInstaller

I used the same implementation and converted to work with Unity.

DependecyResolver

    public class DependencyResolver : IDependencyResolver
    {
        /// <summary> 
        /// Creates the standard resolver. 
        /// </summary> 
        /// IDependencyResolver. 
        public static DependencyResolver CreateStandardResolver()
        {
            Microsoft.Practices.Unity.IUnityContainer container = new Microsoft.Practices.Unity.UnityContainer();
            return new DependencyResolver(container);
        }

        /// <summary> 
        /// Initializes a new instance of the  class. 
        /// </summary> 
        /// The container. 
        public DependencyResolver(Microsoft.Practices.Unity.IUnityContainer container)
        {
            this.Container = container;
        }

        public Microsoft.Practices.Unity.IUnityContainer Container
        {
            get;
            private set;
        }

        public T Resolve<T>(IDictionary args = null)
        {
            return this.Container.Resolve<T>();
        }

        public IEnumerable<T> ResolveAll<T>()
        {
            return this.Container.ResolveAll<T>();
        }
    }

GlassMapperSc

[assembly: WebActivatorEx.PostApplicationStartMethod(typeof(Setup.GlassMapper.GlassMapperSc), "Start")]

namespace Setup.GlassMapper
{
    public static class GlassMapperSc
    {
        public static void Start()
        {
            //create the resolver
            var resolver = DependencyResolver.CreateStandardResolver();

            //install the custom services
            GlassMapperScCustom.ContainerConfig(resolver.Container);

            //create a context
            var context = Glass.Mapper.Context.Create(resolver);
            context.Load(GlassMapperScCustom.GlassLoaders());

            GlassMapperScCustom.PostLoad();
        }
    }
}

GlassMapperScCustom

    public static class GlassMapperScCustom
    {
        public static void ContainerConfig(IUnityContainer container)
        {
            var config = new Config();

            container.Register<IObjectConstructionTask, UnityConstruction>();
            //  config.EnableCaching = false;

            container.Register(new SitecoreInstaller(config));
        }

        public static IConfigurationLoader[] GlassLoaders()
        {
            var attributes = new SitecoreAttributeConfigurationLoader("Sitecore.Models");
            return new IConfigurationLoader[] { attributes };
            //return new IConfigurationLoader[] { attributes, Models.Config.ContentConfig.Load() };
        }

        public static void PostLoad()
        {
            //Comment this code in to activate CodeFist
            /* CODE FIRST START
            var dbs = Sitecore.Configuration.Factory.GetDatabases();
            foreach (var db in dbs)
            {
                var provider = db.GetDataProviders().FirstOrDefault(x => x is GlassDataProvider) as GlassDataProvider;
                if (provider != null)
                {
                    using (new SecurityDisabler())
                    {
                        provider.Initialise(db);
                    }
                }
            }
             * CODE FIRST END
             */
        }
    }

IObjectConstruction pipeline

    public class UnityConstruction : IObjectConstructionTask
    {
        private static object _lock = new object();

        public void Execute(ObjectConstructionArgs args)
        {
            var resolver = args.Context.DependencyResolver as DependencyResolver;
            //check that no other task has created an object
            //also check that this is a dynamic object
            if (args.Result == null && !args.Configuration.Type.IsAssignableFrom(typeof(IDynamicMetaObjectProvider)))
            {
                //check to see if the type is registered with the container
                //if it isn't added it
                if (resolver.Container.IsRegistered(args.Configuration.Type))
                {
                    lock (_lock)
                    {
                        if (resolver.Container.IsRegistered(args.Configuration.Type))
                        {
                            resolver.Container.Register<object>(args.Configuration.Type);
                        }
                    }
                }

                //create instance using SimpleInjector
                var obj = resolver.Container.Resolve<object>(args.Configuration.Type);

                //map properties from item to model
                args.Configuration.MapPropertiesToObject(obj, args.Service, args.AbstractTypeCreationContext);

                //set the new object as the returned result
                args.Result = obj;
            }
        }
    }

Sitecore Installer
Sitecore installer class is really a big one and it uses IWindorInstaller implementation to partition the registration logic. As I am not aware that unity has any extension to support that, I created an extension to support it. As it is huge to copy the entire converted SitecoreIntaller code here, I am just giving the extension interface and method which I used to register the Sitecore Installer. Sitecore Installer and other installer classes will implement IUnityInstaller class and register the mapping of type with IUnityContainer object passed around.

    public interface IUnityInstaller
    {
        void Install(IUnityContainer container);
    }

    public static class UnityExtensions
    {
        public static void Register(this IUnityContainer container, IUnityInstaller installer)
        {
            installer.Install(container);
        }

        public static void Install(this IUnityContainer container, params IUnityInstaller[] installers)
        {
            foreach (var installer in installers)
                installer.Install(container);
        }
    }

I haven’t tested the complete code yet as I am still trying to build the framework piece before starting the actual development. In case if you have any issue drop me a note and I will look into it.

Posted in Sitecore | Tagged , , | Leave a comment

Sitecore Form Authentication Cookie Renewal and Sliding Expiration

Problem

Implement Session Timeout feature in Sitecore and support default form authentication behavior of authentication cookie renewal/expiration and sliding expiration. I looked around the login method and it was called in a standard manner with a call to Sitecore’s Security API’s AuthenticationManager.Login method, which got seven implementation variant, I am listing 3 most commonly used functions, it intern calls the current authentication provider’s login method which internally calls the FormAuthentication.SetAuthCookie after validating the user name and password with Membership Provider.


        /// <summary>
        /// Logs a user into the system if the <paramref name="password" /> is valid.
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <param name="password">The password.</param>
        /// <returns><c>true</c> if user was logged in, otherwise - <c>false</c>.</returns>
        public static bool Login(string userName, string password)
        
        /// <summary>
        /// Logs a user into the system without checking a password.
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <param name="persistent">If set to <c>true</c> (and the provider supports it), the login will be persisted.</param>
        /// <returns><c>true</c> if user was logged in, otherwise - <c>false</c>.</returns>
        public static bool Login(string userName, bool persistent)
        
        /// <summary>
        /// Logs a user into the system if the <paramref name="password" /> is valid.
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <param name="password">The password.</param>
        /// <param name="persistent">If set to <c>true</c> (and the provider supports it), the login will be persisted.</param>
        /// <returns><c>true</c> if user was logged in, otherwise - <c>false</c>.</returns>
        public static bool Login(string userName, string password, bool persistent)

Our developer have used last method for authentication by passing the UserName, Password and Persistent flag. For implementation I got two option either to pass the persistent flag as true or false. Let’s look at the result.

Options

  1. Persistent = true – Per FormAuthentication
  2. documentation, it will create the persistent cookie which will be available across the browser session and will be available till the expiry date based on timeout value. I can not use this option due to cookie being available after browser close and in case someone else open the site before cookie expiration he might see previous user’s data.

  3. Persistent = false – This will not set any expire date on cookie but FormAuthenticationTicket.Expiration
    value based on timeout value defined or default to 30 minutes. This is good as if user closes the browser cookie will be destroyed.

I opted for 2nd approach as it avoid any accidental behavior from user and set the timeout value to 5 minutes to validate the behavior.

Surprise
A quick debug look in immediate window gave a different result.

SlidingExpiration

Though Sitecore.Context.User.IsAuthenticated return true but at the same time it also return true value from FormAuthenticationTicket.Expired field. I am not sure what is really causing this but it could be potentially due to sitecore pipelines running in BeginRequest event but FormAuthentication handles this in AuthenticateRequest event.

I looked at the AuthenticationHelper’s code in Sitecore using Telerik’s justDecompile and it seems it does a null and null/empty value check on authentication ticket but not on expiration flag may be thinking it is automatically taken care by FormAuthenticationModule in the AuthenticateRequest event pipeline. It also expires the cookie if authentication ticket is null or has null/empty value and set a flag (‘SitecoreAuthenticationErrorHandled’) for the request, I have reused the same code below to be compliant with sitecore pipelines.

Solution
A custom Sitecore pipeline to check for FormAuthenticationTicket.Expired flag and expire the cookie if flag value is true, this is currently being partially done inside the Sitecore’s AuthenticationHelper.GetCurrentUser method else renew the ticket based on sliding expiration logic.

I added this pipeline in HttpRequestBegin pipeline before SiteResolver to avoid any issues.

Code

using System;
using System.Web;
using System.Web.Security;
using Sitecore.Diagnostics;
using Sitecore.Pipelines.HttpRequest;

namespace Sitecore.Extensions.Pipelines.HttpRequest
{
    /// <summary>
    /// Authentication renew/expire and sliding expiration processor.
    /// </summary>
    public class RenewExpireAuthentication : HttpRequestProcessor
    {
        /// <summary>
        /// Processes the specified arguments.
        /// </summary>
        /// <param name="args">The request begin arguments.</param>
        public override void Process(HttpRequestArgs args)
        {
            if (args == null)
            {
                return;
            }

            var context = args.Context as HttpContext;
            if (context == null)
            {
                return;
            }

            try
            {
                HttpCookie authCookie = context.Request.Cookies[FormsAuthentication.FormsCookieName];
                if (authCookie == null || (authCookie != null && string.IsNullOrEmpty(authCookie.Value)))
                {
                    return;
                }

                FormsAuthenticationTicket currentAuthTicket = FormsAuthentication.Decrypt(authCookie.Value);
                if (currentAuthTicket == null)
                {
                    return;
                }

                if (currentAuthTicket != null && !string.IsNullOrEmpty(currentAuthTicket.Name))
                {
                    if (currentAuthTicket.Expired)
                    {
                        this.HandleAuthenticationError(context);
                        authCookie.Value = null;
                        return;
                    }
                }

                if (FormsAuthentication.SlidingExpiration)
                {
                    var newTicket = FormsAuthentication.RenewTicketIfOld(currentAuthTicket);
                    if (newTicket != null && newTicket.Expiration > currentAuthTicket.Expiration)
                    {
                        authCookie.Expires = newTicket.Expiration;
                        authCookie.Domain = FormsAuthentication.CookieDomain;
                        authCookie.Path = FormsAuthentication.FormsCookiePath;
                        authCookie.Value = FormsAuthentication.Encrypt(newTicket);
                        context.Response.SetCookie(authCookie);
                    }
                }
            }
            catch
            {
                Log.Warn("Failed to identify cookie expiration and renewal.", this);
            }
        }

        /// <summary>
        /// Handles the authentication error.
        /// </summary>
        /// <param name="context">The current http context.</param>
        private void HandleAuthenticationError(HttpContext context)
        {
            if (context.Items["SitecoreAuthenticationErrorHandled"] != null)
            {
                return;
            }

            var httpCookie = new HttpCookie(FormsAuthentication.FormsCookieName)
            {
                Expires = DateTime.Now.AddYears(-1)
            };

            context.Response.AppendCookie(httpCookie);
            Log.Warn("The current user cannot be resolved from the authentication cookie. The cookie will be removed.", this);
            context.Items["SitecoreAuthenticationErrorHandled"] = new object();
        }
    }
}

Configuration

<httpRequestBegin>
        <processor type="Sitecore.Extensions.Pipelines.HttpRequest.RenewExpireAuthentication, Sitecore.Extensions" patch:before="processor[@type='Sitecore.Pipelines.HttpRequest.SiteResolver, Sitecore.Kernel']"/>
      </httpRequestBegin>

Now, this pipeline takes care of expire/renewing the authentication ticket.

Posted in Sitecore | Tagged , , , | Leave a comment

LogViewer for Enterprise Library Database Logging

History
At some point in my previous two project, I build the LogViewer application to view the logs generated by my app, most of the time is really easy to just go to database and query with select statement with few conditions but it is always good to have a UI tool where you can do search and sorting with few clicks. It’s not just convenient for me personally but team itself.

As, I needed this tool again but I don’t have the source code from previous project, I decided to build it again from scratch and it is fairly easy and quick to get the initial version running. As, I am trying to get my hands on the AngularJS it was a good opportunity to learn and build.

Overview
This tool is build on AngularJS as front end framework with bootstrap, ASP.NET WebApi as backend to support the database interactions and OWIN as framework to keep it light. I have generated the edmx file out of my Enterprise Library database and plugged into a log manager class to retrieve/search the EntLib Log table.

Code
At present it is at early stage and have basic code for configuration and a log manager to fetch the data. Initial version of the code is available on the github.

Limitations
Lots of 🙂 currently, this application support single field search on message field, but this is just start and will keep the source code updated to support more search fields, sorting and other features.

LogViewer Screenshot

Log Viewer

Posted in MVC, WebApi | Tagged , , , , , , | Leave a comment

Dynamic Profile ASP.NET – Update

I received a request about the uses of dynamic keyword in profile declaration and in fact it was valid that while declaring the profile object we should be using concrete profile object and not declaring it as dynamic and rather its properties should be dynamic. I updated the current code by adding a new class ProfileProperties to store all the properties for Profile object.

        /// <summary>
        /// Properties
        /// Dynamic Properies object to hold Profile properties
        /// </summary>
        public dynamic Properties { get; private set; }

Now Profile class’s Init method looks like below.

        /// <summary>
        /// Init
        /// </summary>
        private void Init()
        {
            if (ProfileService != null)
            {
                var _members = ProfileService.GetPropertyValues(this.UserName);
                Properties = new ProfileProperties(_members);
            }
        }

Now it is not required to have the Profile object declared as dynamic rather we can declare it as concrete Profile class.

        public ActionResult Index()
        {
            Profile profile = new Profile(new ProfileService());

            var firstName = profile.Properties.FirstName;
            var lastName = profile.Properties.LastName;
            var name = profile.Properties.Name;
            if (string.IsNullOrWhiteSpace(name))
                profile.Properties.Name = string.Format("Hello Mr.!!! {0} {1}", firstName, lastName);

            var address = profile.Properties.Address;
            if (address == null)
                address = new Address { Street = "Jefferson", Unit = "Line1", City = "Louisville", State = "KY", ZipCode = "40220" };
            profile.Properties.Address = address;
            profile.Save();
            
            return View(profile);
        }

Updated code is available at GitHub

Posted in MVC, Profile | Leave a comment

Dynamic Profile ASP.NET

Recently, I was trying to use ASP.NET Profile Provider for one of my application but soon ran into trouble due to compatibility issues with my CMS system and complexity involved. I decided to build a generic dynamic Profile class and a Provider to support it. Code related to dynamic profile is available on github.

I call this as dynamic profile just because it provide the untyped and runtime access to profile properties, this allows to work with structure without having static type.

There are two main components of Dynamic Profile

  1. Profile class
  2. IProfileService implementation

Profile Class

Profile class is an implementation of DynamicObject with auto detection of current context user or anonymous id, its constructor has a dependency on IProfileService implementation to get/set the data.

Profile class does following

  1. It has a constructor which relies on ASP.NET Anonymous module to track anonymous users or current Identity for authenticated user
  2. An Init method to initialize the properties of the profile from data source with help of IProfileService implementation.
  3. DynamicObject’s method implementation TryGetMember/TrySetMember to get/set the properties in the internal memory.
  4. Save method to persist the profile properties i.e. Property Name and value in the associated store with help of IProfileService Implementation.

IProfileService

IProfileService is the heart of the implementation, it works as Provider for Profile class to retrieve/store profile properties from a persistence store. Actual interface as such is very simple and straight forward with 2 generic method 1) GetPropertyValues 2) SetPropertyValues but implementation can be complex based on the data store chosen and logic required to store the nested values and their type.

    /// <summary>
    /// IProfileService
    /// </summary>
    public interface IProfileService
    {
        /// <summary>
        /// GetPropertyValues
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        Dictionary<string, object> GetPropertyValues(string userName);

        /// <summary>
        /// SetPropertyValues
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="properties"></param>
        void SetPropertyValues(string userName, Dictionary<string, object> properties);
    }

Current implementation stores the values in XML file with file name is unique to either user name or ASP.NET anonymous id, this uses different internal method to serialized/deserialize properties and values in xml along with their type name.

A sample output of current implementation looks like below

<?xml version="1.0" encoding="utf-8"?>
<profile>
  <FirstName type="System.String">Chandra</FirstName>
  <LastName type="System.String">Prakash</LastName>
  <Name type="System.String">Hello Mr.!!! Chandra Prakash </Name>
  <Address type="CPrakash.Web.Profile.Mvc.Models.Address">
    <Street type="System.String">Jefferson</Street>
    <Unit type="System.String">Line1</Unit>
    <City type="System.String">Louisville</City>
    <State type="System.String">KY</State>
    <ZipCode type="System.String">40220</ZipCode>
  </Address>
</profile>

How to use it

As we are trying to store any type of property values in compile time it is required that object declared is of dynamic type.

Declaration

dynamic profile = new Profile(new ProfileService());

Retrieving the values

            var firstName = profile.FirstName;
            var lastName = profile.LastName;
            var address = profile.Address;

Assigning the values (No save)

            if(string.IsNullOrWhiteSpace(name))
                profile.Name = string.Format("Hello Mr.!!! {0} {1}", firstName, lastName);

            if(address == null)
                address = new Address { Street = "MyStree", Unit = "Line1", City = "MyCity", State = "MyState", ZipCode = "MyZipCode" };
            profile.Address = address;

Storing the values in persistence store

 profile.Save();

All code and a sample app with implementation is available on github.

This is very basic implementation and requires enhancement in order to be used in production system, let me know if you have any suggestion and challenges in using this solution.

Posted in MVC, Profile | Tagged , | Leave a comment

Policy Based Authorization in Windows Identity Foundation (WIF) – Part II

Policy based authorization has been gaining ground lately though it is not fully adopted,

XACML – 4 main components

  1. PAP is the Policy Administration Point This is where you administer the policies changing the security rules, and policies. This is separate from the rest of the system as this is decoupled.
  2. PEP is the Policy Enforcement Point. The PEP enforces the access so this is the module that authenticates the request for validity, getting identity information and can also constrain data, cache, and gets the request and then also returns the result, usually a simple Yes or No, however in some systems the actual deliverable, the data being secured is returned from the PEP rather than just a yes/no decision.
  3. PIP is the Policy Information Point. PIP is a service that collects information for the policy decision point to use to make a decision; this is to ensure that all the information that is needed is available. The PIP usually is a front-end to many other backend systems containing the attributes you use for security policies decisions.
  4. PDP is the Policy Decision Point. This is where the magic happens, using a rules engine or something similar, the decision point makes a decision about the access request, and also can loop back to the PIP for more information as the policies are executed.

XACML Workflow –

xacml-workflow_thumb

XACML

  1. You attempt access to a secure system, you will essentially be calling a PEP (enforcement point) which will check your authentication to ensure you are who you say you are, if you are authentic, it will forward request to PDP.
  2. PEP packs this information along with roles and claims to the PDP for a decision to be made about you.
  3. PEP will check cache and return, if not available, it will then try to make a decision, most likely getting information from PIP to make a decision about your authorization access.
  4. PIP will query all identity system usually Active Directory or some Identity system.
  5. PIP will also query any other systems if needed, and send this back to PDP for decision.
  6. PDP caches data from PIP and makes a decision about authorization.
  7. PDP sends decision back to PEP to then allow request or deny.
  8. PEP allows or disallows request based on policies.

Policy –
A policy is an XML document that describes a couple of things needed to grant permission or access to a resource.
1. Subject – who is requesting access, the “WHO”
2. Resource – “WHAT” is the resource being requested.
3. Action – Operation being performed. read, write
Default behavior –
Deny-Overrides: This is that a deny permission will always override a permit, so that if you have 100 rules applied to you, if only 1 of them is deny, you cannot access, this is a more default-secure method for security.

The composition above describes the Scheme of a Policy and Policy set as is required by the XACML standard. In summary you can see that
A Policy has
0 or 1 Targets,
has 1 policy combining algorithm,
0 or 1 Obligations,
1 Rule Combining Algorithm.
A Target has a Subject, Resource, and Action, and Rule, and a Policy Set and Policy.
A Rule has an Effect and 0 or 1 Conditions, and a Rule Combining Algorithm.
A Policy Set has a Target, A Policy Combining Algorithm, and 0 or 1 Obligations.
An Example Policy is shown below:

<Policy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:oasis:names:tc:xacml:1.0:policy" PolicyId="urn:oasis:names:tc:xacml:1.0:conformance-test:IIA1:policy" RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:deny-overrides">
  <Description>
        Policy for Conformance Test IIA001.
    </Description>
  <Target>
    <Subjects>
      <AnySubject />
    </Subjects>
    <Resources>
      <AnyResource />
    </Resources>
    <Actions>
      <AnyAction />
    </Actions>
  </Target>
  <Rule RuleId="urn:oasis:names:tc:xacml:1.0:conformance-test:IIA1:rule" Effect="Permit">
    <Description>
            DemoUser can read about page.
        </Description>
    <Target>
      <Subjects>
        <Subject>
          <SubjectMatch MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
            <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">demouser</AttributeValue>
            <SubjectAttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id" DataType="http://www.w3.org/2001/XMLSchema#string" SubjectCategory="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" MustBePresent="false" />
          </SubjectMatch>
        </Subject>
      </Subjects>
      <Resources>
        <Resource>
          <ResourceMatch MatchId="urn:oasis:names:tc:xacml:1.0:function:anyURI-equal">
            <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#anyURI">http://localhost/StsClient/Home/AccessLinkOne</AttributeValue>
            <ResourceAttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" DataType="http://www.w3.org/2001/XMLSchema#anyURI" MustBePresent="false" />
          </ResourceMatch>
        </Resource>
      </Resources>
      <Actions>
        <Action>
          <ActionMatch MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
            <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">read</AttributeValue>
            <ActionAttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false" />
          </ActionMatch>
        </Action>
      </Actions>
    </Target>
  </Rule>
</Policy>

PIP –
Per XACML reference architecture, PIP is the system entity that acts as a source of attribute values. Basically if there are missing attributes in the XACML request which is sent by PEP, PIP would find them for the PDP to evaluate the policy.

  1. AttributeId must be match
  2. DataType must be match
  3. Issuer must be match .But Issuer is an optional property

Sample Request –

<Request
      xmlns="urn:oasis:names:tc:xacml:1.0:context"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="urn:oasis:names:tc:xacml:1.0:context
        cs-xacml-schema-context-01.xsd">
    <Subject>
        <Attribute
              AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id"
              DataType="http://www.w3.org/2001/XMLSchema#string">
            <AttributeValue>demouser</AttributeValue>
        </Attribute>
    </Subject>
    <Resource>
        <Attribute
              AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id"
              DataType="http://www.w3.org/2001/XMLSchema#anyURI">
            <AttributeValue>http://localhost/StsClient/Home/AccessLinkOne</AttributeValue>
        </Attribute>
    </Resource>
    <Action>
        <Attribute
              AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id"
              DataType="http://www.w3.org/2001/XMLSchema#string">
            <AttributeValue>read</AttributeValue>
        </Attribute>
    </Action>
</Request>

In that case, PDP would look for available PIPs and ask from them to find a matching attribute…
PDP would send following details to PIP

  1. attribute designator —> subject attribute designator
  2. attribute id —-> http://localhost/StsClient/Home/AccessLinkOne
  3. data type —-> http://www.w3.org/2001/XMLSchema#string
  4. issuer —-> null
  5. Subject Attribute value in request —> demouser

Implementation logic in PIP would know that PDP wants the email of the user Bob. Therefore PIP would contact external attribute source and find the email address of it. Email address of user “bob” would be returned from the PIP to the PDP
Therefore, finally PDP just have to perform the “string-regexp-match” function on these two attribute values “bob@wso2.com” and “[0-9a-zA-Z]+@wso2.com”.
PIP Attribute Finder should implement following methods

Init (Properties properties) Here you can write the logic to initialize your module. Any properties that are defined in the entitlement-config.xml file, can be access here.
b). GetAttributeValues (String subject, String resource, String action, String environment, String attributeId, URI issuer) Here you can write the logic to find your attribute value
c). GetSupportedAttributes() Here you can write the logic to find all the attribute ids supported by your module

PDP – Should implement following methods

1. bool Evaluate(String xacmlRequest)
Where you need to input a XML String object of XACML request and XACML response also is received as XML String
2. bool GetDecisionByAttributes(String subject, String resource, String action, String[] environment)
Where you can pass one attribute value of a subject, a resource and an action as input value.

Example

I have modified the sample with xacml.net to demonstrate the policy based authorization.

How the sample works –

Example flow

Custom Authorization Manager will create a request with following information and pass it to PDP

  1. Subject
  2. Resource
  3. Action

A sample Xml Request looks like this


<?xml version="1.0" encoding="UTF-8"?>
<Request xmlns="urn:oasis:names:tc:xacml:1.0:context"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="urn:oasis:names:tc:xacml:1.0:context
        cs-xacml-schema-context-01.xsd">
    <Subject>
        <Attribute
              AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id"
              DataType="http://www.w3.org/2001/XMLSchema#string">
            <AttributeValue>demouser</AttributeValue>
        </Attribute>
    </Subject>
    <Resource>
        <Attribute 
              AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id"
              DataType="http://www.w3.org/2001/XMLSchema#anyURI">
            <AttributeValue>http://localhost/StsClient/Home/AccessLinkOne</AttributeValue>
        </Attribute>
    </Resource>
    <Action>
        <Attribute
              AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id"
              DataType="http://www.w3.org/2001/XMLSchema#string">
            <AttributeValue>read</AttributeValue>
        </Attribute>
    </Action>
</Request>

PDP will take the request and run against the policy defined.
A sample policy look like this.

<?xml version="1.0" encoding="utf-8"?>
<Policy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:oasis:names:tc:xacml:1.0:policy" PolicyId="urn:oasis:names:tc:xacml:1.0:conformance-test:IIA1:policy" RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:deny-overrides">
  <Description>
        Policy for Conformance Test IIA001.
    </Description>
  <Target>
    <Subjects>
      <AnySubject />
    </Subjects>
    <Resources>
      <AnyResource />
    </Resources>
    <Actions>
      <AnyAction />
    </Actions>
  </Target>
  <Rule RuleId="urn:oasis:names:tc:xacml:1.0:conformance-test:IIA1:rule" Effect="Permit">
    <Description>
            DemoUser can read about page.
        </Description>
    <Target>
      <Subjects>
        <Subject>
          <SubjectMatch MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
            <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">demouser</AttributeValue>
            <SubjectAttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id" DataType="http://www.w3.org/2001/XMLSchema#string" SubjectCategory="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" MustBePresent="false" />
          </SubjectMatch>
        </Subject>
      </Subjects>
      <Resources>
        <Resource>
          <ResourceMatch MatchId="urn:oasis:names:tc:xacml:1.0:function:anyURI-equal">
            <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#anyURI">http://localhost/StsClient/Home/AccessLinkOne</AttributeValue>
            <ResourceAttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" DataType="http://www.w3.org/2001/XMLSchema#anyURI" MustBePresent="false" />
          </ResourceMatch>
        </Resource>
      </Resources>
      <Actions>
        <Action>
          <ActionMatch MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
            <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">read</AttributeValue>
            <ActionAttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false" />
          </ActionMatch>
        </Action>
      </Actions>
    </Target>
  </Rule>
</Policy>

PDP will result the decision with either Permit or Deny
XACML PDP call looks like this

var r = new EvaluationEngine().Evaluate((PolicyDocument)PolicyLoader.LoadPolicyDocument(policyStream), (ContextDocument) ContextLoader.LoadContextDocument(requestSteam));

Where r is the result from PDP.
CustomAuthorizationManager will allow or deny the access to resource based on PDP’s decsion

 if (r != null && r.Results != null && r.Results.Count > 0)
                    return r.Results[0].Decision == Decision.Permit;

An example source code for this article can be found at github.

Reference –
http://viswaug.wordpress.com/2007/11/29/xacml-a-standard-that-i-wish-i-had-known-about-earlier/
http://sourceforge.net/projects/xacmlpdp/
http://mvpos.sourceforge.net/
http://xacmlinfo.com/
http://codingbliss.com/?tag=xacml
http://www.ibm.com/developerworks/xml/library/x-xacml/

Posted in Security, WIF | Leave a comment