Security issues
XData is able the application to take a full control over data access rights and rights to execute any data aware business logic. Inside the XData has designed a complete data security solution for control access to some properties of data objects, access to data objects corresponds some rules, access to standard (CRUD), or custom data aware business logic.
For using this ability is required to implement interface ISecuritySession and use it as parameter of GetRepository method of data scope interface to get security sensible repository.
XData is not specify the way to authentication and authorization. Your application can use any existing technologies or products on the market. Here the synthetic but simple and demonstrative example of ISecuritySession implementation:
public class MySecuritySession : SecuritySession
{
private const string Manager = "Manager";
private const string Guest = "Guest";
private const string Chief = "Chief";
private const string Clerk = "Clerk";
public static MySecuritySession CreateSecuritySession
(string userName, string password)
{
if (userName == "Admin" && password == "123")
return new MySecuritySession(userName, new string[0], true);
if (userName == "Manager" && password == "111")
return new MySecuritySession(userName, new[] { Manager, Clerk });
if (userName == "Guest" && password == "222")
return new MySecuritySession(userName, new[] { Guest });
if (userName == "Chief" && password == "333")
return new MySecuritySession(userName, new[] { Chief, Manager, Clerk });
if (userName == "Clerk" && password == "444")
return new MySecuritySession(userName, new[] { Clerk });
RiseUnauthorizedAccessException();
return null;
}
/// <exception cref="XDataSecurityException"></exception>
[DebuggerStepThrough]
[DebuggerNonUserCode]
private static void RiseUnauthorizedAccessException()
{
throw new XDataSecurityException("XDataObjectTest system");
}
public MySecuritySession
(string userName, string[] roles, bool isSupervisor = false)
: base(userName, roles, isSupervisor) { }
protected override void InitializeSession()
{
//Hide some columns from Guests
RegisterRestrictedProperties("", typeof(Invoice),
new[] { Guest.SetValue(new[] {
Property<Invoice>(x => x.DocAmount),
Property<Invoice>(x => x.DocLastChange),
Property<Invoice>(x => x.Scan),
Property<Invoice>(x => x.Source),
Property<Invoice>(x => x.CustomerTo),
Property<Invoice>(x => x.DeliveryType)
}) });
RegisterGrantedActions("", typeof(Invoice), new[] {
//Grant all actions to Chief
Chief.SetValue(new [] { Actions.All }),
//Grant all CRUD but TestCustomLogic is denied for Manager
Manager.SetValue(new [] { Actions.CRUD }),
//Grant update only for Clerk
Clerk.SetValue(new [] { Actions.Update }),
//Grant execute TestCustomLogic only for Guest
Guest.SetValue(new[] { Action(() => Invoice.TestCustomLogic) })
});
//Hide non ACTIVE invoices from Guests
RegisterSecurityFilters("", typeof(Invoice), new[] {
Guest.SetValue<string, Expression>(
(Expression<Func<Invoice, bool>>)(x => x.DocStateCode == "ACTIVE")) });
}
}
To simplify the ISecuritySession interface implementation use the NuGet package XData Security package. This package provide an abstract class SecuritySession implemented base functionality and useful helpers. This functionality is shipped separately because of security session using is optional.
Important
Required to override the constructor SecuritySession(string userName, string[] roles, bool isSupervisor = false) used in three-tier architecture on server side, and override method InitializeSession. Method InitializeSession is used to cache access rues profile.
Tip
Caching of all users security rules (as exposed in sample above) is not effective. This for simplify demonstration only. Security session is current user security describer. Recommended to cache rules for current user only using initialized before calling of InitializeSession properties: UserName, Roles and IsSupervisor.
In sample above take a look on using caching methods: RegisterRestrictedProperties, RegisterGrantedActions and RegisterSecurityFilters, and a helper methods: Property and Action.
When describing access rules to actions (standard and custom) use constants defined in Actions static class:
- All - all actions over data object, including standard (CRUD) and custom named actions
- CRUD - all standard actions: Create, Update, Delete
- Create - create new data object action
- Update - update data object properties
- Delete - delete data object