Skip to content
This repository was archived by the owner on Dec 9, 2022. It is now read-only.

SecurityContext

Kristoffer Ahl edited this page Oct 29, 2013 · 27 revisions

SecurityContext

When a policy is enforced it is passed an instance of ISecurityContext. ISecurityContext contains information about the current state of things. Such as "Is the user authenticated?" and "What are the roles of the current user?".

ISecurityContext.Data

As of version 2.0, ISecurityContext contains a Data property. The Data property is an ExpandoObject that allows you to add custom data to it. You can then get to it from within a policy when it is enforced.

By default the Data property contains the RouteValueDictionary for the current request (x.Data.RouteValues). This allows you to write policies that use route data to determine if a policy is met or not.

Modifying ISecurityContext.Data

In order to add data to the Data property of ISecurityContext you need to specify a modifyer. This is done by calling configuration.Advanced.ModifySecurityContext(context => {}). In the closure you can access the Data property and add you custom data. So if you wanted to add information about the HTTP method used you could do something like this:

configuration.Advanced.ModifySecurityContext(context =>
	context.Data.HttpMethod = HttpContext.Current.Request.HttpMethod
	);

Creating a custom ISecurityContext

FluentSecurity allows you to create and use custom security contexts. Simply implement the ISecurityContext interface and register the instance in your IoC-container. When FluentSecurity needs an instance of ISecurityContext it will ask your container for it. It can be resolved multiple times per HTTP request so make sure you set the appropriate lifecycle in your container. Note that registering a context in your container will require you to manually add route values to the Data property. See the next section for an easier and better approach.

Working with typed contexts

With the addition of the Data property on ISecurityContext it's become much easier to create policies that can access route values etc. But wouldn't it be nice to be able to work with typed contexts? Well, you can! Let's say you want an easy way to access the value of the id route parameter. Here's an example:

public class ContextWithId : SecurityContextWrapper
{
	public string Id { get; private set; } 

	public ContextWithId(ISecurityContext securityContext) : base(securityContext)
	{
		Id = Data.RouteValues["Id"];
	}
}
public class PolicyConsumingId : SecurityPolicyBase<ContextWithId>
{
	public override PolicyResult Enforce(ContextWithId securityContext)
	{
		var currentId = securityContext.Id;
		... Do stuff with the id ...
	}
}

As you can see it's as easy as creating a context inheriting from SecurityContextWrapper (or MvcSecurityContext). To use a typed context in a policy you need to inherit from SecurityPolicyBase<T> where T is the type of context. This means that you can have different types of contexts for each policy. In order for this to work properly you need to make sure your context has a single constructor argument of type ISecurityContext.

A note about ISecurityContext and IoC-containers.

You generally don't want to register contexts in your IoC-container! It is possible but it is not recommended as it has a few known side effects:

  • You will manually have to add route values to the Data property
  • You will have to implement the interface from scratch

MvcSecurityContext

The MvcSecurityContext class is simply a helper context that gives you an easy way to access route values. So instead of typing Data.RouteValues you get a property called RouteValues on your context that is of type RouteValueDictionary. MvcSecurityContext can be used as is or be inherited from.

Clone this wiki locally