views:

22

answers:

1

Hi

I have a usercontrol which is responsible for presenting creation and change of users. The usercontrol is bound to an entity delivered by a RIA Service:

[MetadataType(typeof(User.UserMetadata))]
public partial class User
{
    internal class UserMetadata
    {
        protected UserMetadata() {}

        [Required]
        public string Name { get; set; }

        [Exclude]
        public string PasswordHash { get; set; }

        [Exclude]
        public int PasswordSalt { get; set; }

        [Required]
        public string ShortName { get; set; }

        [Include]
        public IEnumerable<UserRole> UserRoles { get; set; }
    }

    [DataMember]
    [RegularExpression("^.*[^a-zA-Z0-9].*$", ErrorMessageResourceName = "BadPasswordStrength", ErrorMessageResourceType = typeof(ErrorResources))]
    [StringLength(25, MinimumLength = 6)]
    public string NewPassword { get; set; }
}

When creating a new user, the field "NewPassword" is required - but when changing properties of an existing user, it is not (it is used for password-changes).

What is the best approach to solve this? I have several ideas, but they all feels a little bit crappy :-)

Thanks

+1  A: 

It appears you are passing your current passwords back to the GUI. There is no need to ever do that. That would create a potential security hole

Suggest you treat password changing as a separate service call, not just a simple record editing exercise. RIA services supports Invoke Operations which are basically arbitrary direct-calls to your RIA service. The only restriction on Invoke operations is that they cannot return complex types (not a problem for this example).

Pass your current logged-in user identifier, the current password (encoded) and the new password (encoded) and do all the work server side. Return a simple success boolean value.

Just some suggestions, I am happy to see other people's ideas on this one :)

Enough already
I'll second this. You should never include passwords in your entities. Instead, make them method parameters and make sure they are not included in the uri (use POST). Also, switch to using https on deplyment. I've posted some guidance on how to do this with ASP.NET Membership and how to use https on my blog. http://blogs.msdn.com/b/kylemc/archive/2010/05/10/using-asp-net-membership-in-silverlight.aspx http://blogs.msdn.com/b/kylemc/archive/2010/05/26/ria-services-using-https.aspx
Kyle McClellan
No I never push the password to the GUI, the NewPassword-Property is "computed" and do not map to a table-attribute. It's just there, to take password-changes and initial passwords from the user.Just to make sure. Your proposal is to remove this property and introduce a service which is only responsible to set/reset the password? Sounds ok - even I don't really understand the difference.
Daniel
@Daniel: If you are only sending the password back already encrypted, your idea also works. Are you actually encrypting your password on the client? That was my major concern.
Enough already
@HiTech Magic: I encrypt the password on the client yes. But my problem is still unsolved: How should I handle, that the password is in one case mandatory (creation of a new user) and in another case, it is optional (change password of a user). So the question is more about Validation...
Daniel
That goes back to my original answer. Keep *new password* in your User class if you want and implement *change password* via an explicit RIA Invoke Operation call. Databinding can sometimes guide you into doing things you would not normally do. Bind the password change fields to other (ViewModel) properties and not your RIA model. New Password and Change Password are conceptually *not* the same thing (although they look similar on a form).
Enough already
ok got it, sounds right :-) Thanks a lot
Daniel