How to return more detailed error when user cannot be validated - asp.net-mvc-3

I am working on creating a custom membership class for my asp.net project. In the MembershipProvider class, function for user validation is defined as follows.
public abstract bool ValidateUser(string username, string password);
The problem is validation can be failed for several reason, so I want to provide more detailed description as to why login failed (e.g., user is lockedout etc) but that cannnot be done via a bool return type. I certainly can create one of my method for validation as follows
public RichStatusDetailsEnum ValidateUser(string username, string password);
Problem with above is that I will not be able to call this method in a generic way (just by Membership.ValidateUser). Rather I will have to instantiate object of my custom membership provider etc etc. Does anyone else has encountered same issue and if there are any better ways of handling this type of situation?

As per this MSDN resource, the return will tell you if it is valid. There are only two parameters (username and password). If it is a false return, then you know one of them is off. You can always test if the UserName is correct by calling Membership.GetUser(). If the MembershipUser object returned is not null, then you know the UserName is correct. In which case, that would lead you to believe that if ValidateUser() fails, it is a bad password.
To see if the user is locked out: for the MembershipUser object that gets returned from GetUser(), you can test if the user is locked out by the property Membershipuser.IsLockedOut.

Description
One way to get this done is
Store the reason, why the validation failed, in the HttpContext.Current.Items Collection
If ValidateUser failed, get the data and do something (like add an error to ModelState.AddModelError("Property","Message");
Sample
public override bool ValidateUser(string username, string password)
{
// your custom logic goes here
HttpContext.Current.Items["ValidateUserResult"] = ValidateUserFailed.UserNameWasWrong;
return false;
}
public enum ValidateUserFailed
{
UserNameWasWrong, PasswordWasWrong, BecauseIDontLikeYou
}
your other class
More Information
MSDN - HttpContext.Items Property
MSDN - ViewDataDictionary.ModelState Property

Related

Partial Entity Updates in WebAPI PUT/POST

Say you have a repository method to update a Document:
public Document UpdateDocument(Document document)
{
Document serverDocument = _db.Documents.Find(document.Id);
serverDocument.Title = document.Title;
serverDocument.Content = document.Content;
_db.SaveChanges();
return serverDocument;
}
In this case, the entity has two properties. When updating a Document, both of these properties are required in the JSON request, so a request to PUT /api/folder with a body of
{
"documentId" = "1",
"title" = "Updated Title"
}
would return an error because "content" was not provided. The reason I'm doing this is because, even for nullable properties and properties that the user doesn't update, it seems safer to force the client to specify these fields in the request to avoid overwriting unspecified fields with nulls serverside.
This has led me to the practice of always requiring every updatable property in PUT and POST requests, even if it means specifying null for those properties.
Is this cool, or is there a pattern/practice that I haven't learned about yet that might facilitate partial updates by sending only what is needed over the wire?
The best practice in API design is to use HTTP PATCH for partial updates.
In fact, use cases like yours are the very reason why IETF introduced it in the first place.
RFC 5789 defines it very precisely:
PATCH is used to apply partial modifications to a resource.
A new method is necessary to improve interoperability and prevent
errors. The PUT method is already defined to overwrite a resource
with a complete new body, and cannot be reused to do partial changes.
Otherwise, proxies and caches, and even clients and servers, may get
confused as to the result of the operation. POST is already used but
without broad interoperability (for one, there is no standard way to
discover patch format support).
Mark Nottingham has written a great article about the use of PATCH in API design - http://www.mnot.net/blog/2012/09/05/patch
In your case, that would be:
[AcceptVerbs("PATCH")]
public Document PatchDocument(Document document)
{
Document serverDocument = _db.Documents.Find(document.Id);
serverDocument.Title = document.Title;
serverDocument.Content = document.Content;
_db.SaveChanges();
return serverDocument;
}
Is this cool, or is there a pattern/practice that I haven't learned
about yet that might facilitate partial updates by sending only what
is needed over the wire?
A good practice of doing a POST or PUT is to only include values that you need for that specific request. In doing the UpdateDocument you should ask yourself what "really should be done here"? If you have a hundred fields on that object do you need to update all of them or only part of them. What "action" are you really trying to do?
Let's have an illustration for those questions, say we have a User object that has the following fields:
public class User {
public int Id {get;set;}
public string Username {get;set;}
public string RealName {get;set;}
public string Password {get;set;}
public string Bio {get;set;}
}
You then have two use cases:
Update the profile of a User
Update the password of a User
When you do each of those you will not, or it's a good idea to, have one update method that will do both. Instead of having a generic UpdateUser method you should have the following methods:
UpdateProfile
UpdatePassword
Methods that accepts fields that they just need, nothing more, nothing less.
public User UpdateProfile(int id, string username, string realname, string bio) {
}
public User UpdatePassword(int id, string password) {
}
Now comes the question:
I have a use case that a "user action" allows for an update on
multiple fields where some of the fields can have "no input" from the
user but I don't want to update that field in my model.
Suppose a user updates his/her profile and provided values for Username, RealName but not for Bio. But you do not want to set Bio as null or empty if it has a value already. Then that becomes a part of your application's business logic and that should be handled explicitly.
public User UpdateProfile(int id, string username, string realname, string bio) {
var user = db.Users.Find(id);
// perhaps a validation here (e.g. if user is not null)
user.Username = username;
user.RealName = realname;
if (!string.IsNullOrEmptyWHiteSpace(bio)) {
user.Bio = bio;
}
}

Server-side validation

I am having trouble figuring out how to get server-side DbContext validation errors back to the client. I understand that Breeze has default validators that react to a few of the attributes such as Required, but what about all the other attributes? I could write a custom JavaScript validator for Breeze that will check on the client side, but I also need to check to make sure the entity is valid on the server-side.
For example, the application requires a Person to to have a valid email address. A malicious user comes along and gets an email address past the client and posts to the server with a data that would not pass the EmailAddress validator. Thus far my experience with Breeze is that the email address will save and not bubble up any DbContext Entity Framework errors.
Assuming the model below, what would be the best way to get any entity validation errors?
public class PeopleContext : DbContext
{
public PeopleContext()
: base("name=ConnectionString"){ }
public DbSet<Person> People { get; set; }
}
public class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[EmailAddress]
[Required]
public string Email { get; set; }
}
UPDATE 1:
Here are some instructions to re-create the issue that I am experiencing.
Follow the instructions to create the "Todo" sample (http://www.breezejs.com/documentation/start-nuget)
Add a new custom validator to the BreezeSampleTodoItem.cs file:
[AttributeUsage(AttributeTargets.Property)]
public class CustomValidator : ValidationAttribute
{
public override Boolean IsValid(Object value)
{
string val = (string)value;
if (!string.IsNullOrEmpty(val) && val == "Error")
{
ErrorMessage = "{0} equal the word 'Error'";
return false;
}
return true;
}
}
Decorate the Description field with the new custom validator:
[CustomValidator]
public string Description { get; set; }
Add the proper usings of course (System and System.ComponentModel.DataAnnotations).
Run the project.
In one of the description fields type "Error" and save.
This is where I would expect to see an error come up through Breeze, or even an DbEntityValidationException be thrown from Entity Framework. I have tried on 2 separate computers with the same result. The entity saves to the database as if there were no error. In fact, if you put a breakpoint anywhere inside IsValid method of the custom validator you will see that its not even being called.
As of Breeze v 0.78.1 all registered DbContext server side validations will now execute during an EntityManager SaveChanges call. Any exceptions encountered will cause the save to rollback, and any validation errors to be serialized back to the Breeze client.
Note that this functionality is not yet supported for older ObjectContext ( as opposed to DbContext) based EF models.
And ... thanks to adamlj for discovering this issue and suggesting the solution.
I'm not sure what you mean by
get server-side DbContext validation errors back to the client
You could mean that you want the validation error messages to be sent to the client. But the rest of your question suggests that you want to know (a) how to run a custom validation on the server and (b) how to acquire and run a corresponding JavaScript version of that validation on the client. I will address this interpretation of your question.
Server
The Entity Framework (which you're using in your example) automatically runs Data Annotation validation rules for you ... unless you've disabled that feature manually. If you create custom validation rules in the proper way, EF will run these as well. This post by Daniel Wertheim describes how to write such rules. I can't vouch for that post in every detail but it seems correct to me. It even defines a custom Email-validationattribute!
If authoring a custom Data Annotation validation rule seems too Baroque to you (as it often does to me), you can write and call your own validation logic in one of the BeforeSave... methods discussed in "Server-side Interception".
I think these are your best server options. On to the client ...
Client
Breeze registers client-side JavaScript validations to match certain of the server-side Data Annotations (e.g., Required and MaxLength) that come across the wire in the metadata. As I write, custom Data Annotations are not recognized nor included in the metadata and they have no out-of-the-box analogs on the client. If you want the client to prescreen your entities using these rules, you'll have to write your own corresponding JavaScript validators and register them for the pertinent entity types as discussed in the Validation documentation page.
If you have suggestions or better alternatives, we'd love to hear them.

Play framework 2: one model approach

The problem:
When programming with play framework I feel that I'm stumbling with same problem than in many times at the past which is creating several models of the same type just because I want to add, update or use different data about certain model in different use cases.
Let me explain, lets consider of a example where I have 2 different views: register and login
I would have following User model:
/**
* Example User class (simple annotations for demo purposes).
*
*/
#Entity
public class User {
#Id
public Long id;
#Required
public String email;
#Required
public String password;
#Required
public String firstName;
#Required
public String lastName;
}
In case of registering: I would have all corresponding fields in register.scala.html : email, password, firstName, lastName - because I will need them all when I register, right?
But also I would want to use repeatPassword field to confirm that user has typed password correctly, so I would add this into User model:
#Required
#Transient
public String repeatPassword;
Ok, then I would extend this model to have repeat password confirmation check in order to correct my "automatic" validations when form is submitted, like this:
public String validate() {
if(!password.equals(repeatPassword)) {
return "Passwords doesn't match.";
}
return null;
}
}
So even now I would have one extra attribute repeatPassword which is not persisted to database but used within registration.
Problem #1: Our model starts to go confusing piece by piece.
In case of login: I would want to use same model because its a User which is trying to sign in, right? But instead of all the fields I would only need email, password.
Problem #2: My User model cant be used in login because its already customized to be used within registration - I would need to move repeatPassword and validate() method to separate UserRegistation model, plus duplicate firstName lastName etc. fields or mix using both User and UserRegistration model within registration and to render two different forms to same registration view = confusing.
Problem #3: My login page cant use User model because it has annotations in place, if I dont add all the necessary fields like firstName, lastName etc. I will get errors. Again, I would need to create separate UserLogin model just because I want to login to work.? Example below:
public class UserLogin {
#Required
public String email;
#Required
public String password;
public String validate() {
if(User.authenticate(email, password) == null) {
return "Invalid user or password";
}
return null;
}
}
So very fast, I would have 3 different models just to represent User, one of them is persisted to database and two others is used to validate errors when we are completing login and registration functionality at template side.
So my question is: How on earth I should begin to solve this mess? code complexity is rising very fast :) Should I create separate models.template and models.database packages where template models are only ones within annotations and in case of no errors I start to fill real model before saving or updating its info to database? I need desperately answers from you guys/girls, Can we make one model approach? thnx in advance.
I'll start from the end: you don't need to use whole model for changing password or loggin-in (also you don't need to create separate, 'non-persisted' sub-models), although Form<YourModel> is useful while filling large objects, you can just avoid them and rely on common DynamicForm.
In such case of course it won't use constraints added with annotations to the model's fields but you can validate them manually.
For an example: in registration form you can check if #Required fields like email, firstName, lastName exists (tip: also add MinLength and MaxLength constraints), but you should remove #Required annotation from password field.
Next after checking if the form hasn't any errors you can check if password and repeatedPassword are the same and it they are identical you can also add some individual (advised) strength check - most probably it wouldn't be possible with the annotations in the model.
In case of logging form the thing is ever easier: using DynamicForm data just try to find existing User with given password if result is null that means, the user doesn't exists or password is invalid.
Finally, tip: There is ready-to-use, full-stack authentication and authorisation module available for Play 2.0 by Joscha Feth (and I'm huge advocate of this solution.)

MVC3 URL parameters - avoiding malicious attacks/security flaws

When navigating to a new webpage, is there a "Best Practice" for passing Ids around.
For example, a person registers to use a website, they get given an Id, this needs to be passed around the rest of the website/pages where it is used to retrieve relevant data from a database.
If the Id is passed in the url: http://myWebsite.com/User/Details/1234, the user could change it to
http://myWebsite.com/User/Details/4567 and potentially retireve a different user's details.
Putting this value in a hidden field and then POSTing wouldn't be great either as "view source" would display the value.
Many thanks
That's why you should always verify that this id belongs to the currently authenticated user. The currently authenticated user is stored in the forms authentication cookie and is something that the user cannot change because the value is encrypted. This cookie is emitted when the user logs in and you can access it everywhere where you have an instance to HttpContextBase (which is pretty much almost anywhere in the V and C parts of the MVC pattern).
For example, like this:
[Authorize]
public ActionResult Foo(int id)
{
string currentUser = httpContext.User.Identity.Name;
// TODO: go ahead and check in your backed that the id
// belongs to the currently connected user
...
}
Obviously writing those checks over and over again in all controller actions could quickly become boring, not to mention the DRYness of the approach. That's why it is recommended to write a custom Authorize attribute which will perform those checks before even entering into the controller action. Then you will decorate your controller actions with this custom attribute and you will know for sure that if the code has reached inside the action it means that the current user is the owner of the id passed as parameter. The way this id is passed as parameter doesn't really matter. Could be route data, query string, POST, whatever. The user can modify it as much as he likes. The important part is that you ensure that the value he entered is coherent with your domain authorization logic.
So:
public class AuthorizeOwnerAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var authorized = base.AuthorizeCore(httpContext);
if (!authorized)
{
// the user is either not authenticated or not authorized
// no need to continue any further
return false;
}
// at this stage we know that the user is authenticated and
// authorized (in roles), so let's go ahead and see who this
// user is
string username = httpContext.User.Identity.Name;
// now let's read the id. In this example I fetch it from
// the route data but you could adapt according to your needs
string id = httpContext.Request.RequestContext.RouteData.Values["id"] as string;
// Now that we know the user and the id let's go ahead and
// check in our backend if the user is really the owner
// of this id:
return IsOwner(username, id);
}
private bool IsOwner(string username, string id)
{
// go ahead and hit the backend
throw new NotImplementedException();
}
}
and then:
[AuthorizeOwner]
public ActionResult Foo(int id)
{
...
}

How do you handle data validation in the model using ColdFusion Model-Glue?

MVC best practices state that the model should handle input/data validation. Let's say that we have a model that creates new user accounts, with the following fields and constraints:
Username - not null, not already in DB
Password - not null, alphanumeric only
E-mail - not null, not already in DB, valid e-mail format
We have an AccountModel with a CreateNewUser() function:
component
{
public void function CreateNewUser(string username, string password, string email)
{
// create account
}
}
Then we have a controller that processes a form post and tells the model to create the account:
component
{
public void function NewUser()
{
var username = event.getValue("username");
var password = event.getValue("password");
var email = event.getValue("email");
var accountModel = new AccountModel();
accountModel.CreateNewUser(username, password, email);
event.addResult("UserCreated");
}
Now I want to add validation. If the user fails to provide input for all three fields, the application should show the user three validation error messages. This is easy enough to do in the controller:
// assumes that ValidateInput() is a function on the controller that returns an array
var validationErrors = ValidateInput(username, password, email);
// if there were any validation errors, return a ValidationError result
if (len(validationErrors)
{
event.setValue("validationerrors", validationErrors);
event.addResult("ValidationError");
}
else
{
event.addResult("UserCreated");
}
And the view will pull the validationerrors variable and display the error messages.
However, this logic is supposed to reside in the model. How do I do this? I can think of two ways:
Method 1: Move ValidateInput() from the controller to the model. Now the controller has to call ValidateInput() first before CreateNewUser(). If the programmer forgets to do this, CreateNewUser() will throw a validation exception. The downside to this is that now every data operation that requires validation will need an if/else block.
Method 2: Forego having to call ValidateInput() and just call CreateNewUser() directly. If there were any validation errors, an exception will be thrown and it will contain the error message array. This method would work in C#, but it looks like ColdFusion does not support returning of data with the exception, only an exception message and type. Also, every data operation will require a try/catch block.
Method 3: ??
How would you handle validation in this case? Is method 1 what most people do when it comes to validation in the model? Or do people typically use method 2? Or is there a method 3 that I'm not thinking of?
I don't think you should couple the validation of the user's data entry to the creation of the user's account: they are too different things.
If you couple the two together, it means you're basically doing form validation every time you create an account, which doesn't seem right to me.
I see form validation as a UI concern, more than a concern of the objects that might be ultimately created from that data. Obviously your createNewUser() method has its own business rules (which will probably closely mirror that of the validation for a create-new-user form, but they are still separate concerns).
It is possibly a bit unorthodox, but I will put a validateUserData() (or something) method in my User CFC which the form-validation model then calls to help with the validation. This means the business rules for a user are in the same place, and can be called separately. Thereafter, createNewUser() works on a garbage-in/garbage-out principle.
Sidenote: createNewUser() is a bit of a tautological name, innit? What other sort of user would you be creating other than a new one? Also, if it's in your Account.cfc; is it a new user or a new account that's being created? If an account and a user are not synonymous and an account might exist without a user (or vice-versa), perhaps you ought to have a User.cfc too. Then again, this code you've given us could simply be for the purposes of illustration, and you've got all this covered.

Resources