Monday, June 23, 2008

Windows workflow foundation - Part 1

Windows Workflow Foundation Overview
Windows Workflow Foundation is a framework that enables users to create system or human workflows in their applications written for Windows Vista, Windows XP, and the Windows Server 2003 family. It consists of a namespace, an in-process workflow engine, and designers for Visual Studio. Application like Business Process Management, Document management, Page Flow etc might benefit from the WF.
What is a workflow?
A workflow is a set of elemental units called activities that are stored as a model that describes a real-world process. It describes the order of execution and dependent relationships between the activities. This work passes through the model from start to finish, and activities might be executed by people or by system functions.
Windows Workflow Foundation supports two types of workflow
• Sequential workflow – Each step in the workflow leads to another step. Steps in the sequential workflow don’t wait for human interaction to perform the next step.
• State-machine workflow – The behavior of this workflow is determined by the state of the workflow or by the transition of the state. A step does not perform an activity unless something happens.
Workflow runtime
The workflow runtime engine is responsible for creating and maintaining a workflow instance. The runtime engine can support multiple workflow instances running concurrently. When a workflow model is compiled, it can be executed inside any Windows process including console applications, forms-based applications, Windows Services, ASP.NET Web sites, and Web services. Because a workflow is hosted in process, a workflow can easily communicate with its host application. Remember that there can be only one instance of runtime in the App domain.
It is the runtime engine that starts individual workflow tasks, fire events for different situations and keeps track of services that can be plugged into the execution environment.
Structure of the WorkflowRuntime class
public class WorkflowRuntime : IServiceProvider, IDisposable
{
public WorkflowRuntime();
public WorkflowRuntime(string configSectionName);
public WorkflowRuntime(WorkflowRuntimeSection settings);

public bool IsStarted { get; }
public string Name { get; set; }

public event EventHandler ServicesExceptionNotHandled;
public event EventHandler Started;
public event EventHandler Stopped;
public event EventHandler WorkflowAborted;
public event EventHandler WorkflowCompleted;
public event EventHandler WorkflowCreated;
public event EventHandler WorkflowIdled;
public event EventHandler WorkflowLoaded;
public event EventHandler WorkflowPersisted;
public event EventHandler WorkflowResumed;
public event EventHandler WorkflowStarted;
public event EventHandler WorkflowSuspended;
public event EventHandler WorkflowTerminated;
public event EventHandler WorkflowUnloaded;

public void AddService(object service);
public WorkflowInstance CreateWorkflow(Type workflowType);
public WorkflowInstance CreateWorkflow(XmlReader workflowDefinitionReader);
public WorkflowInstance CreateWorkflow(Type workflowType, Dictionary namedArgumentValues);
public WorkflowInstance CreateWorkflow(Type workflowType, Dictionary namedArgumentValues, Guid instanceId);
public WorkflowInstance CreateWorkflow(XmlReader workflowDefinitionReader, XmlReader rulesReader, Dictionary namedArgumentValues);
public WorkflowInstance CreateWorkflow(XmlReader workflowDefinitionReader, XmlReader rulesReader, Dictionary namedArgumentValues, Guid instanceId);
public ReadOnlyCollection<T> GetAllServices<T>();
public ReadOnlyCollection<object> GetAllServices(Type serviceType);
public ReadOnlyCollection<WorkflowInstance> GetLoadedWorkflows();
public T GetService<T>();
public object GetService(Type serviceType);
public WorkflowInstance GetWorkflow(Guid instanceId);
public void RemoveService(object service);
public void StartRuntime();
public void StopRuntime();
}

In the next part of the series I will show how to create a workflow and use the runtime exposed methods for controlling the activities.

Tuesday, June 3, 2008

PrincipalPermission attribute and authorization rules

The ASP.NET pipeline takes an incoming request and processes it through a number of steps. For example the authentication module waits for the AuthenticateRequest event, at which point it inspects the incoming request for an authentication ticket. If an authentication ticket is found, a GenericPrincipal object is created and assigned to the HttpContext.User property.
The HttpContext.User property is a GenericPrincipal object. This GenericPrincipal object has an IIdentity which includes a reference to the authentication ticket. The GenericPrincipal class contains the bare minimum functionality needed by a class that implements IPrincipal – it just has an Identity property and an IsInRole method. When the authentication module creates the GenericPrincipal, it passes in an empty string array to the GenericPrincipal’s constructor. Consequently, any call to IsInRole will always return false. When ASP.NET’s Roles framework is enabled it creates a custom principal object of type RolePrincipal and overwrites the authentication module-created GenericPrincipal object. It does this in order to customize the principal’s IsInRole method to interface with the Roles framework’s API. You can also create a custom IPrincipal object and associate with the User object for role handling.
In this article I will explain how to use the PrincipalPermission attribute available in the System.Security.Permissions namespace to authenticate users using the Identity in your ASP.NET / Winforms application. I have used the details from Scott’s blog for explaining the concept.
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public class UserManager
{
[PrincipalPermission(SecurityAction.Demand, Role = "Admin" , Name="Prajeesh")]
public User AddUser(User user)
{
//Implement the add user code here.
}

[PrincipalPermission(SecurityAction.Demand, Role = "User")]
public void SearchUsersWithName(String userName)
{
//Implement the search users code here.
}
}
By using the PrincipalPermission attribute and decorating with the respective members to the class UserManager we have made sure that the user must be authenticated before this class can be instantiated during a web request. We can also add security demands on the methods of the class and associate the methods with roles. This will make sure that the methods can be invoked for particular roles only.
You can also use the PrincipalPermission attribute with win forms application, but you may need to set the PrincipalPolicy in the constructor of the class as explained below
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public class UserManager
{
private WindowsPrincipal windowsPrincipal;

public UserManager()
{
windowsPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent()); AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
}

[PrincipalPermission(SecurityAction.Demand, Role = "Admin", Name="Prajeesh")]
public User AddUser(User user)
{
//Implement the add user code here.
}

[PrincipalPermission(SecurityAction.Demand, Role = "User")]
public void SearchUsersWithName(String userName)
{
//Implement the search users code here.
}
}
This approach will prevent the methods of the class to be invoked by raising a security exception even if there is a security hole in the presentation layer code.