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);
}
}
The fact is that using OData is orthogonal to authentication and authorization. That is to say, you may secure an OData API in any way you can secure a generic RESTful API.
The $select option specifies a subset of properties to include in the response body. For example, to get only the name and price of each product, use the following query: Console Copy. GET http://localhost/odata/Products?$select=Price,Name.
For this tutorial, we'll use Entity Framework (EF) Code First to create the back-end database. Web API OData does not require EF. Use any data-access layer that can translate database entities into models.
OData defines parameters that can be used to modify an OData query. The client sends these parameters in the query string of the request URI. For example, to sort the results, a client uses the $orderby parameter: http://localhost/Products?$orderby=Name. The OData specification calls these parameters query options.
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.
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With