To provide a bit of background, I was asked to add some restrictions to an application where we had to control access to certain actions based on roles, but the stumbling block came when I was asked to add further restrictions to prevent particular users from accessing data specific to other users. Sounds like something FubuMvc should be easily able to provide, but I am sure my lack of understanding has made my implementation akin to performing dentistry via the belly button. To make matters a bit more tricky the developers that built the application are no longer working here, so I cannot ask them to explain the best practices or help in general.
Here is my code which (I hope) should explain better than my words:
public class MyAuthorizationPolicy
{
private readonly ISecurityContext securityContext;
public MyAuthorizationPolicy( ISecurityContext securityContext)
{
this.securityContext = securityContext;
}
public AuthorizationRight RightsFor(IFubuRequest request)
{
// stuff
if (request.Has<string>())
{
var id = request.Get<string>();
var claims = ((ClaimsIdentity) securityContext.CurrentUser.Identity).Claims;
var partnerIdsForCurrentUser = claims
.Where(claim => claim.ClaimType == ClaimTypes.Partner)
.Select(claim => Guid.Parse(claim.Value));
var match = partnerIdsForCurrentUser.Any(i => i == new Guid(id));
if (!match)
return AuthorizationRight.Deny;
}
// more stuff
}
}
[ AllowRole( Roles.AllowRole) ]
public class Get_Id_Handler
{
public Get_Id_Handler( IBindingContext context, ICurrentHttpRequest request )
{
// How can I avoid doing this, maybe some kind of route mapping that could be accessed in the policy?
var fubuRequest = context.Service<IFubuRequest>();
var PartnerId = GetPartnerIdFromRequest(request);
fubuRequest.Set(typeof(string), PartnerId);
}
public ViewModelExecute( GetInputModel inputModel )
private string GetPartnerIdFromRequest(ICurrentHttpRequest request)
{
// I want the last part which would be a guid representing the users claim (he might have more than one but at this point the user is trying to access this particular claim)
return new Uri(request.FullUrl()).Segments.Skip(4).Take(1).Single(); // I wish I knew how to get this data in a 'better' way
}
}
Ok, I know at this point a lot people are having brain haemorrhages from looking at this code, I would really love to be educated how I can achieve what I am doing here in a method that is not hacky. The code does work and is wired up successfully but I would really like to have the policy check the current context of the user and the page they are accessing to ensure they have the claims to match their request.
I guess I would like to have some light shed on this and learn a number of things along the way.
Sorry for my butchery the framework :(