WebApi OData per user security on property
Asked Answered
S

1

6

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);
    }
}
Sassanid answered 1/10, 2015 at 14:58 Comment(0)
H
1

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.
    }
}
Hoashis answered 3/2, 2016 at 5:1 Comment(1)
According to the above answer, how can an additional condition be added to the query? Providing a code example will be highly appreciated! E.G where (x => x.Secret == UserA.Secret);Dusk

© 2022 - 2024 — McMap. All rights reserved.