Reputation: 10792
I have some entities which have data that must only be accessible for some users.
public class Foo
{
public virtual Bar { get; set; }
...
}
public class Bar
{
public string Secret { get; set; }
...
}
For example Bar.Secret
must only be accessible by UserA
but not by UserB
.
I could so something like this:
public class BarsController : ODataController
{
[EnableQuery]
public IHttpActionResult Get()
{
if (User.Identity.Name != "UserA")
return Unauthorized();
return _db.Bars();
}
}
Besides that being a bad implementation. It doesn't cover this controller:
public class FoosController : ODataController
{
[EnableQuery]
public IHttpActionResult Get()
{
return _db.Foos();
}
}
Which could be called with /odata/Foos?$expand=Bars
and then I could view Bar.Secret
. I can't just disable $expand
on Foo
because that query is totally legit for UserA
and also needed.
Is there a way to make OData validate the queries against some predicate that involves the requested entities.
Something like
public class SecureEnableQueryAttribute : EnableQueryAttribute
{
public bool ValidateResult(IEnumerable<T> entities)
{
return entities.All(x => x.Secret == UserA.Secret);
}
}
Upvotes: 6
Views: 441
Reputation: 2935
You can validate the query options before the query is executed and fail if the user is not authorized to retrieve the requested data. To do this, derive from EnableQueryAttribute
and override ValidateQuery
.
public class SecureEnableQueryAttribute : EnableQueryAttribute
{
public virtual void ValidateQuery(HttpRequestMessage request, ODataQueryOptions queryOptions)
{
base.ValidateQuery(request, queryOptions);
// Insert custom logic, possibly looking at queryOptions.SelectExpand
// or queryOptions.RawValues.
}
}
Upvotes: 1