Data Security using Entity Framework - entity-framework

What options/solutions are there for securing data using Entity Framework?
I do not talk about forms login and such here, just assume that the users are authenticated or not.
To illustrate, i attached one of my web api controllers and i wonder if this is the way to do it. The reason why i ask is that i wonder if there are easier ways to do this than writing all this logic to what data to expose in all my controllers.
Also, when looking into a system like breezejs and odata where i can add $expand=TrafficImages to my queries, i would not want users to be able to get my hole database.
So to summarize, what ways are there to securing the data exposed such the users cant download sensible data.
[AllowAnonymous]
public object GetTheoryTests()
{
var identity = ((ClaimsIdentity)((ClaimsPrincipal)HttpContext.Current.User).Identity);
//if (HttpContext.Current.User.Identity.IsAuthenticated)
if (!identity.IsAuthenticated)
return db.TheoryTests.Include(t=>t.TrafficImages).Where(t=>t.PublicAvalible)
.Select(t => new { Id = t.Id, Title = t.Title, Images = t.TrafficImages }).AsEnumerable();
if (User.IsInRole("WebAdmins"))
return db.TheoryTests.AsEnumerable();
var key = identity.GetProvider();
var member = db.Members.Include(m=>m.PayedTheoryTests).SingleOrDefault(m=>m.Identities.Any(
i=>i.identityprovider == key.provider &&
i.nameidentifier == key.id));
if(member!=null)
return db.TheoryTests.Include(t => t.TrafficImages).Where(t => t.PublicAvalible).Select(t => new { Id = t.Id, Title = t.Title, Images = t.TrafficImages }).AsEnumerable();
else
return db.TheoryTests.Include(t => t.TrafficImages).Where(t => t.PublicAvalible)
.Union(member.PayedTheoryTests).Select(t => new { Id = t.Id, Title = t.Title, Images = t.TrafficImages }).AsEnumerable();
}
When thinking about it, what i miss is something like a viewmodel untop of my database depending on the state of the user. Would it be a solution to create two entity frameworks ontop of the same database, one for limited data display and one for more advanced operations?

Meanwhile, until QueryInterceptors arrive, you should take other steps. First, you should look into the techniques for securing a Web API controller or method, a subject beyond the scope of this answer.
Second, w/r/t $expand, you are quite right to be wary of that feature. You may want to inspect which expansions are requested for some controller methods and/or disallow it altogether for others.
Fortunately, this is relatively easy to do. You have access to the request query string. You can detect the presence of "$expand" in that string and analyze it if you want to allow certain expansions and forbid others.
Breeze will add helpers for this in future. You'll have to process the string until then.
You may want to create your own action filter for this purpose if you're up to it.

Great question!. We are currently working on something called QueryInterceptors that will allow you to examine and possibly change or reject the query that was submitted to the server. The "Principal" would be a available context object within each QueryInterceptor method. Please vote for this feature on the "Breeze" website at www.breezejs.com.

Related

Inclusion and Exclusion of Model Properties in Entity Framework

I have a user model and there are different properties I want to be obtainable in different circumstances,
I have a WebAPI that handles the User Model, and for different actions, I need certain properties excluded.
E.g.
When I do /API/Users -> I want to omit the passwords as this will enable someone to see the hashes of all the passwords.
However I can't outright omit the passwords as the password is required by actions such as login.
What is the best solution to enable omission of certain fields depending on the circumstances?
As a work around I added this code to my API Action
// GET: api/Users
public List<User> GetUsers()
{
return db.Users.ToList().Select(u => { u.password = ""; return u; }).ToList();
}
but surely there is a more elegant solution than this. Ideally I would like to add an annotation to the action that precludes certain properties from the result set

Sail.js - routing to methods, custom policies & PATCH method

I have a few questions that I couldn't find answers anywhere online.
Does sails.js framework support HTTP PATCH method? If not - does anyone know if there is a planned feature in the future?
By default if I create method in a controller it is accessible with GET request is it the routes.js file where I need to specify that method is accessible only via POST or other type of methods?
How would you create a policy that would allow to change protected fields on entity only for specific rights having users. I.e: user that created entity can change "name", "description" fields but would not be able to change "comments" array unless user is ADMIN?
How would you add a custom header to "find" method which specifies how many items there are in database? I.e.: I have /api/posts/ and I do query for finding specific items {skip: 20; limit: 20} I would like to get response with those items and total count of items that would match query without SKIP and LIMIT modifiers. One thing that comes to my mind is that a policy that adds that that custom header would be a good choice but maybe there is a better one.
Is there any way to write a middle-ware that would be executed just before sending response to the client. I.e.: I just want to filter output JSON not to containt some values or add my own without touching the controller method.
Thank you in advance
I can help with 2 and 5. In my own experience, here is what I have done:
2) I usually just check req.method in the controller. If it's not a method I want to support, I respond with a 404 page. For example:
module.exports = {
myAction: function(req, res){
if (req.method != 'POST')
return res.notFound();
// Desired controller action logic here
}
}
5) I create services in api/services when I want to do this. You define functions in a service that accept callbacks as arguments so that you can then send your response from the controller after the service function finishes executing. You can access any service by the name of the file. For example, if I had MyService.js in api/services, and I needed it to work with the request body, I would add a function to it like this:
exports.myServiceFunction = function(requestBody, callback){
// Work with the request body and data access here to create
// data to give back to the controller
callback(data);
};
Then, I can use this service from the controller like so:
module.exports = {
myAction: function(req, res){
MyService.myServiceFunction(req.body, function(data){
res.json(data);
});
}
}
In your case, the data that the service sends back to the controller through the callback would be the filtered JSON.
I'm sorry I can't answer your other questions, but I hope this helps a bit. I'm still new to Sails.js and am constantly learning new things, so others might have better suggestions. Still, I hope I have answered two of your questions.

Sails.js: Sending a 409 response if a duplicate record is posted

Not sure how to do this in sails.js, but I'd like to be able to, when creating a new object on the API, check to see if that object's id exists and if it does, send a 409 conflict response, and if it doesn't, create the object like normal.
For the sake of discussion, I've created a Brand model.
I'm assuming that I would override the create function in the BrandController, search for the brand based on req.param('id') and if it exists, send the error response. But I'm not sure if I'm doing this correctly, as I can't seem to get anything to work.
Anyone have ideas?
I ended up using a policy for this particular use case.
Under config/policies, I created a isRecordUnique policy:
/**
* recordIsUnique
*
* #module :: Policy
* #description :: Simple policy to check that a record is unique
*
* #docs :: http://sailsjs.org/#!documentation/policies
*
*/
module.exports = function(req, res, next) {
Brand.findOne({ id: req.body.id}).done(function (err, brand) {
if (brand) {
res.send(409);
} else {
next();
}
});
};
This allowed me to avoid overriding any CRUD functions and it seemed to fit the definition of a policy, in that only checks one thing.
To tie my policy to my create function, I modified config/policies by adding:
BrandController: {
create: 'isRecordUnique'
}
That's it. Took me way too long to figure this out, but I think it's a good approach.
Well since this is MVC you are thinking correctly that the Control should be enforcing this logic. However, as this is basic uniqueness by the primary id the model should know/understand and help enforce this.
Model should identity the conflict.
In sails the coder is responsible for the defining uniqueness, but I would have the model object do it not the controller.
The controller should route/respond by sending the view which is effectively http 409.
Yes the controller create method should be used in this case, as sails wants to provide CRUD routes for you. Assuming it is a logical create not some resultant or odd non-restful side effect.
I think of Sails.js by default providing a model controller, so use their perspective since you are using their framework. There are many approaches to Control/Model relationships.
res.view([view, options[, fn]])
Ideally the view would control the http response code, the message, any special additional headers. The view just happens to be extremely basic, but could vary in the future.
You could always set headers and response with JSON from the controller but views offer you flexibility in the future, like decoupling, the reason the MVC pattern exists. However, sails also seems to value convenience, so if it is a small app maybe directly from the controller.

Retrieve Activities of an entity in CRM 2011 using CRM sdk rest

I have used SDK Rest javascript that came with CRM SDK kit to retrieve attributes (fields) of crm entities, manipulate the same.
For example I use this SDK rest javascript as follows in my web resource;
var options = "$select=FullName,SystemUserId&$filter=(IsDisabled eq false) and (AccessMode/Value ne 3)";
SDK.REST.retrieveMultipleRecords("SystemUser", options, retrieveUsersCallBack, function (error) { alert(error.message); }, UserRetrieveComplete);
I would like to know if there is a way to retrieve "notes and activities" mainly emails regarding a particular entity, so that i can move the same to another entity based on certain condition.
Thank you all
Sorry I just landed on the answer which is as follows
var options = "$select=Lead_Emails&$expand=Lead_Emails&$filter=LeadId eq guid"+"'"+idOfCurrentLead+"'";
But I would like to know how do i move these emails to another entity (opportunity) record on qualify.
var options = "$select=Lead_Emails&$expand=Lead_Emails&$filter=LeadId eq guid"+"'"+idOfCurrentLead+"'";
Sorry Guys I just figured out the answer.

ServiceStack Routing with ravendb ids

I've an entity with an ID of
public string ID {get;set;}
activities/1
(which comes from RavenDB).
I'm registering the following routes in my ServiceStack AppHost
Routes
.Add<Activity>("/activities")
.Add<Activity("/activities/{id}");
I'm using a backbone app to POST and PUT to my REST Service.
What happens out-of-the-box:
id property is serialized into the json as "activities/1"
id property is encoded into route as "activities%2F1"
ServiceStack gives precedence to the URL based id property, so my string gets the encoded value which is no use to RavenDb directly.
The options I'm aware of:
Change backbone to post to "/activities" and let the JSON Serialiser kick in
Change RavenDb ID generation to use hyphens rather than slashes
Make my Id property parse for the encoded %2F on set and convert to a slash
Both have disadvantages in that I either lose RESTfulness in my API, which is undesirable, or I don't follow RavenDb conventions, which are usually sensible out-of-the-fox. Also, I've a personal preference for having slashes.
So I'm wondering if there are any other options in servicestack that I could use to sort this issue that involve less compromise? Either Serialiser customisation or wildcard routing are in my head....
I have the same problem with ASP.Net WebAPI, so I don't think this is so much a ServiceStack issue, but just a general concern with dealing with Raven style id's on a REST URL.
For example, let's say I query GET: /api/users and return a result like:
[{
Id:"users/1",
Name:"John"
},
{
Id:"users/2",
Name:"Mary"
}]
Now I want to get a specific user. If I follow pure REST approach, the Id would be gathered from this document, and then I would pass it in the id part of the url. The problem here is that this ends up looking like GET: /api/users/users/1 which is not just confusing, but the slash gets in the way of how WebAPI (and ServiceStack) route url parameters to action methods.
The compromise I made was to treat the id as an integer from the URL's perspective only. So the client calls GET: /api/users/1, and I define my method as public User Get(int id).
The cool part is that Raven's session.Load(id) has overloads that take either the full string form, or the integer form, so you don't have to translate most of the time.
If you DO find yourself needing to translate the id, you can use this extension method:
public static string GetStringIdFor<T>(this IDocumentSession session, int id)
{
var c = session.Advanced.DocumentStore.Conventions;
return c.FindFullDocumentKeyFromNonStringIdentifier(id, typeof (T), false);
}
Calling it is simple as session.GetStringIdFor<User>(id). I usually only have to translate manually if I'm doing something with the id other than immediately loading a document.
I understand that by translating the ids like this, that I'm breaking some REST purist conventions, but I think this is reasonable given the circumstances. I'd be interested in any alternative approaches anyone comes up with.
I had this problem when trying out Durandal JS with RavenDB.
My workaround was to change the URL very slightly to get it to work. So in your example:
GET /api/users/users/1
Became
GET /api/users/?id=users/1
From jQuery, this becomes:
var vm = {};
vm.users = [];
$.get("/api/users/?" + $.param( { id: "users/1" })
.done(function(data) {
vm.users = data;
});