I have a User object in my Linq-To-Sql mapping. There is a password attribute on it that I want to deserialize when submitted by a user--for example, during login. I never want to pass this attribute back to the user, though, since it will contain the encrypted version of the actual password and I'd rather not expose any information about the password or the encryption method. Is there a way to object-wide tell Linq-To-Sql to never pass the Password attribute when returning a User object?
I use https for encryption, mostly because just in accessing the service, you by default enforce your encryption, which saves on client side code. You have a few possible answers though:
Blank out the password when you return the User Object from the WCF side. (You can change the value of the password of the object, and just not save the change.. then return the object to the client )
Use a custom object for your login response that returns only the necessary information for your client.
Implement a Data Transfer Object pattern, with a nuget package like AutoMapper.
If you aren't salting and hashing your passwords, please please please consider it.
In the case where I never want to serialize an object, it is best to hook into the OnSerializing event. Since I'm using Linq-To-Sql, the OnSerializing event has already been captured by my DataContext's designer.cs for tracking serialization state for lazing loading entity references. Adding another function decorated with [OnSerializing] throws an error in System.ServiceModel.Activation, so I had to find another route. Here's my solution:
Modify DataContext.designer.cs
In DataContext.designer.cs, I added
[global::System.Runtime.Serialization.OnSerializingAttribute()]
[global::System.ComponentModel.EditorBrowsableAttribute(EditorBrowsableState.Never)]
public void OnSerializing(StreamingContext context)
{
this.serializing = true;
// custom function to handle my logic
this.ClearPassword();
}
Add Method to my custom Class Definition
In my User.cs file, I have a partial class definition. Therefore, all I need to do is add the ClearPassword method to my partial class definition:
partial class User
{
private void ClearPassword()
{
this.Password = null;
}
//* OTHER CODE *//
}
Now, no matter how I'm interacting with User objects, passwords are never passed to the client, as desired.
Related
I have a .net 6.0 Blazor Server web application that is essentially a basic registration form (contact information: First Name, Last Name, Email, Phone, etc).
I'm trying to create a custom ValidationAttribute (EmailUniqueAttribute) that will check for uniqueness of the form's email field against the backend database. If it exists already IsValid returns false , else if it doesn't it returns true.
The problem I'm encountering is that it appears that you can only pass constant arguments into a custom ValidationAttribute? In this case the argument that would need to be used in the validation is a boolean value that is determined at runtime based on user input to the email field and the result of a database query to check for its existence (IsUnique).
I thought about injecting my service to the back end calls into the custom ValidationAttribute and checking for uniqueness at the time of validation (anti pattern debates aside) but it looks like support for DI into a ValidationAttribute isn't available until .Net 7.1 preview based on other articles and questions I've read on this topic here.
How exactly should I go about this?
Well there are several ways to solve it:
A first one would be to setup the email-column inside your database with a unique constraint (you can do this for every solution/way). Duplicate entries will then throw an error on save. Simply catch the save-error and show them to your frontend.
Another way would be to handle errors a bit earlier by using the OnSubmit method of your EditForm. Inject a Service that reads all mail-entries from your database and check them against the entered email address. It should be sufficient to call the service once at OnInitialized to prevent multiple database selections for probably the same list.
A more convenient way for the user would be to use the above mentioned service to check the mail uniqueness while typing into the InputText field. You can hook up to several events there like #oninput.
You could also use some custom Validation packages like FluentValidation that extend the validation system by a more complex system which allows more complicated conditions to check against.
EDIT:
You can still make use of a custom attribute if desired:
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
public class EmailUniquenessAttribute : DataTypeAttribute
{
private EmailService _service;
public EmailUniquenessAttribute() : base(DataType.EmailAddress)
{
// You can use your DI system to get the desired service here
_service = new EmailService();
}
public override bool IsValid(object value)
{
if (value == null)
{
return true;
}
if (value is not string valueAsString)
{
return false;
}
return _service.EmailAlreadyExistsInDatabase(valueAsString);
}
}
I'm a bit confused about OData entities structure. Let's take an example of user entity:
public class User {
[Required]
public string Name;
[Required]
public string Surname;
[Required]
public string Password;
}
And then we adding it to EDM model:
var type = builder.AddEntityType(typeof(User));
builder.AddEntitySet("Users", type);
Fair enough but... Of course we don't want to expose Password. Fortunately there is a lot of way to exclude password from exposure.
One of them is to just set it to null on return which in my opinion feels wrong as the field is marked as Required and returning null just feels wrong.
More common one is to ignore it in EDM model. But there is a problem with that solution, namely POST method will no longer receive every data required to create User.
public ActionResult<User> Post([FromBody] User user)
{
// user missing password
How is user supposed to log-in without specifying password ?
I feel like excluding password from EDM model is not the correct way to do it as well.
Ideal solution would be to use two DTO's that would separate UserInitiator data structure (that would include password property but not have some other properties like id) and UserInfo that will contain all 'safe to read' data. Unfortunately OData doesn't seems to allow such a separation.
So, how should i handle password property in correct way ?
You could add user creation/login as a separate action, that way it can have a custom parameter type. You can read about OData actions here. For example, the edm for a user registration action might look something like:
var action = builder.EntityType<User>().Action("Register");
action.Parameter<UserWithPwdDto>("user");
Where User is the entity type of the controller which doesn't include the password property, and UserWithPwdDto has the password property and is only used by actions that require that property.
Also I hope the user class you show in your question is not used as your database model, you should never save passwords as plain-text in your database.
so I have some models being displayed in a default view. I am trying to figure out if I want to hash the password with Crypto.HashPassword() method. Do I do this in the controller or the model or where? I did research on how to do it, but I am just finding different method and not where the action takes place. Beginner to MVC and asp.net, so any point in the right direction would be major help. Thank you in advance.
You generally will want to perform the hash operation in the controller, and store the hash result value in the model.
Taking for example a simple user login to your website:
When the user account is first created, you'll call Crypto.HashPassword(pwd) to calculate the hash value of the password the user has set. You can do this in the controller, inside the action where the user registers a new account.
The resulting hash value needs to be stored in the Model (e.g. in the DB) so that you can retrieve it later.
When the same user tries to login next time, you'll need to call Crypto.VerifyHashedPassword(storedHash, submittedPwd). Crypto class hashes the submitted pwd with the same IV and Salt, and returns True if they match (pwd is correct), or False if they don't (pwd is wrong).
If you are new to MVC and ASP.Net, you may want to look at ASP.Net Forms Authentication (such as this page on MSDN), which you can use for authenticating users without having to roll your own custom solution.
I'd define the user class like this:
public class User
{
private string PasswordHash {get; set;} //assuming your db supports serializing private properties. If not increase visibility as necessary.
public void SetPassword(string newPassword)
{
PasswordHash = PasswordHasher.CreateHash(newPassword);
}
public bool VerifyPassword(string passwordCandidate)
{
return PasswordHasher.Verify(PasswordHash, passwordCandidate);
}
}
I would not have a User.Password property, since you never store it, and there is no simple mapping between passwords and hashes.
The PasswordHash property should only be accessed by the database serializer and through these two functions. The controller should fetch the user and then call these methods to verify/change the password.
I also recommend using a custom hasher with similar API to the Crypto class. Crypto has a hardcoded iteration count with a rather small value.
There could be many ways of doing it..
I ideally I would mark the password property with a custom attribute name [Encrypt(true)]. So then when the property is saving to the database, you got to track the models property that marked by Encrypt attribute separately (inside DbContext Saving event). Then you could encrypt that and save it to the database inside the said saving event.
A custom attribute and a generic solution like this could come handy when you want to encrypt any other sensitive data that you want to save in to your database later too.
I have a clientside typeahead that pulls back a json list and presents options to the user for a specific list of places that they can enter for an input field.
On the server I want to make sure that the submitted form data matches one of these places. Realistically it should unless someone was being malicious and posting data from fiddler or something like that.
I supply the data to the typeahead from a list stored in Redis. I've read that it's bad practice to contact a database from within an attribute but I would like to check for the existence of the place in the redis list before allowing the logic flow to continue.
I could cache the list statically on startup in each webserver instance however this now means that if the list changes at all then all the servers would have to be restarted to get the changes.
Perhaps instead of using Validation Attributes I should be using a fluent validator?
http://fluentvalidation.codeplex.com/wikipage?title=ValidatorFactory&referringTitle=Documentation
I've read that it's bad practice to contact a database from within an
attribute [...]
Your attribute does not need to know about any database or anything of that matter. What your attribute needs to do is to call a Service to do the job. The implementation of the Service will be hidden from your Attribute's point of view.
interface IValidationService
{
bool DoesPlaceExist(Place place);
}
class RedisValidationService : IValidationService
{
bool DoesPlaceExist(Place place)
{
// crazy redis magic ...
}
}
class PlaceValidationAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var validationService = new RedisValidationService(); // ideally use IoC
var isValid = validationService.DoesPlaceExists(new Place(value));
// ... this is over simplified to just show the idea
// return blah blah
}
i have tried to surf the internet but i could not get anything related to what i want.
This is in relation to ASP.Net. But could be any other instance as well.
Following is my attribute
class SomeAttribute :Attribute
{
string someparam;
string SomeParam
{
get{ return someparam;}
set { someparam = val;}
//the value generated for someparam is dynamically generated with respect to some attribute present in the request header.
}
}
it's similar to the [Authorize] attribute that .net uses in its asp .net memberships to validate if the user has logged in and it redirects him back to log in page if validation fails.
I have an attribute associated with a method like below:
[SomeAttribute]
public void someFunction
{
//i want to retrieve here the value of someparam jus generated before entering this method.
}
Note that i don't pass any value or used any named properties in this attribute. It is simply going to check a condition for me whenever the method is called and return true or false and accordingly the function is either called or not.
In my case, After validating, it generates a value and that value has to be shared with the function to which it is associated 'somefunction'.
i know reflections can help me get the attributes associated with a function and the value of its properties.
But here i dont want to fetch the value from some other function. And i dont want to just fetch the attribute either.
As i mentioned earlier when the function is called the attribute will work upon that. What the attribute does is fetches some data from request header and does some processing and generates a value. Now this value has to be passed on to the function just after that.
Well, what you want to accomplish is certainly possible, but it would not be an optimal use of the run-time or the MVC model.
In this particular case, think of an attribute as an annotation. It's something you use to mark a function, controller, etc. so that its execution behaves differently at run-time. The attribute itself should not be doing the bulk of the work, rather just signalling to other pieces in your design to behave differently.
It seems like you want to check some header values, and calculate something based off of that. You can use extension methods off of a Request class to accomplish this.
Now, let's say that inside your Controller's function, you want to guarantee that the header values exist. You can have an attribute called RequireHeaderValues that implements IActionFilter. The attribute would check the header for the required values and if they don't exist, it routes the response to another location or somehow indicates error. This way, when inside your function, you call the extension method off the Request object, you are guaranteed that the values will exist. The MVC run-time will automatically call your filter attribute for you. For more info, see this.