21

We have the following scenario:

  1. MVVM userinterface where a user can place his password (actually a PasswordBox)
  2. Server that shall do some work
  3. Server connects to some Database that requires authentification

And I already read this Question on PasswordBox in MVVM

But there is no answer on how to do! Just lots over "never ever do that".

What is the correct way of passing a password around? How to resolve the security issues?

There is no proper way of Binding to the PasswordBox and the Password shall not be stored somewhere, okay.

So, what is the MVVM way of doing such things?

Even if the pattern is broken, is there a good way to achieve such things?

Thought of a Func<string> to retrieve it, but without Binding this will get a mess...

Update Same for initialising the PasswordBox from a (hopefully encrypted) password store. Isn't that breaking the MVVM pattern? The User does not want to enter the password each time he starts the application or wants to work with the database I believe.

Community
  • 1
  • 1
Mare Infinitus
  • 8,024
  • 8
  • 64
  • 113

5 Answers5

42

Personally I just pass the entire PasswordBox control to my LoginCommand

I know it breaks MVVM because the ViewModel layer now references a View-specific object, but I think in this specific case it's OK.

So I might have XAML that looks like this:

<Button Content="Login" 
        Command="{Binding LoginCommand}" 
        CommandParameter="{Binding ElementName=MyPasswordBox}" />

And a LoginCommand that does something like this:

private void Login(object obj)
{
    PasswordBox pwBox = obj as PasswordBox;

    SomeBlackBoxClass.ValidatePassword(UserName, pwBox.Password);
}

I suppose you could also run some kind of encryption algorithm on the value and compare the hash of that value to the hash of the user's password too

private void Login(object obj)
{
    PasswordBox pwBox = obj as PasswordBox;
    var encryptedPassword = SomeLibrary.EncryptValue(pwBox.Password, someKey);

    if (encryptedPassword == User.EncryptedPassword)
        // Success
}

I'm no expert on the PasswordBox control or security, but I do know that you don't want to be storing the user's password in plain text anywhere in memory within your application

(Technically, it's stored as plain text in PasswordBox.Password - you can use something like Snoop to verify this if you want - however typically the PasswordBox doesn't exist for longer than it takes the user to login, and the actual "password" is just text entered by the user, which may or may not be correct. A keylogger could get you the same information.)

BDL
  • 21,052
  • 22
  • 49
  • 55
Rachel
  • 130,264
  • 66
  • 304
  • 490
  • So I shall really hand over a PasswordBox to the Server? – Mare Infinitus Mar 13 '13 at 16:50
  • 1
    @MareInfinitus Personally I would encrypt the `PasswordBox.Password` on the Client side, and pass the UserName and encrypted password to the server instead of passing the unencrypted PasswordBox object to the server. `PasswordBox.Password` is plain text, so I don't like keeping the `PasswordBox` object around longer than I have to. – Rachel Mar 13 '13 at 16:53
  • Sounds good, will have a closer look at that. At the moment I have a command binding like you suggested – Mare Infinitus Mar 13 '13 at 16:56
  • @MareInfinitus The systems I've seen which allow you to "remember the password" so you don't have to type it in every time have all stored the encrypted password somewhere locally on the machine, such as in the registry, and the encrypted value is compared against the encrypted password in the Users table – Rachel Mar 14 '13 at 12:05
  • Just hoped someone has a real solution to that problem, but your solution is a way to go! Thank you! – Mare Infinitus Mar 15 '13 at 19:57
  • So you're sending a control into the ViewModel? Isn't that a bad idea? – Carlo Jan 27 '14 at 23:16
  • A really out-of-the-box solution. Thank you! – Mc_Topaz Mar 09 '23 at 15:30
7

I have solved this problem by creating a UserControl that exposes a SecureString dependency property that can be bound to. This method keeps the password in a SecureString at all times, and doesn't "break" MVVM.

UserControl

XAML

<UserControl x:Class="Example.PasswordUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         mc:Ignorable="d"
         d:DesignHeight="300" d:DesignWidth="300">
    <Grid>       
        <PasswordBox Name="PasswordBox" />
    </Grid>
</UserControl>

CS

public partial class PasswordUserControl : UserControl
{
    public SecureString Password
    {
        get { return (SecureString) GetValue(PasswordProperty); }
        set { SetValue(PasswordProperty, value); }
    }
    public static readonly DependencyProperty PasswordProperty =
        DependencyProperty.Register("Password", typeof(SecureString), typeof(UserCredentialsInputControl),
            new PropertyMetadata(default(SecureString)));


    public PasswordUserControl()
    {
        InitializeComponent();

        // Update DependencyProperty whenever the password changes
        PasswordBox.PasswordChanged += (sender, args) => {
            Password = ((PasswordBox) sender).SecurePassword;
        };
    }
}

Example usage

Using the control is very straightforward, just bind the password DependencyProperty on the control to a Password property on your ViewModel. The ViewModel's Password property should be a SecureString.

<controls:PasswordUserControl Password="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

Change the Mode and UpdateSource trigger on the binding to whatever is best for you.

If you need the password in plain text, the following page describes the proper way to convert between SecureString and string: http://blogs.msdn.com/b/fpintos/archive/2009/06/12/how-to-properly-convert-securestring-to-string.aspx. Of course you shouldn't store the plain text string...

DinoM
  • 144
  • 1
  • 4
  • This might be best solution, but because code sample is incomplete its an useless one... – Aistis Taraskevicius Jun 29 '17 at 10:53
  • 1
    Hi Aistis, could you please explain why you think the sample is incomplete? I thought I had provided enough information to solve the problem and implement a solution, but I'm happy to update the original post if you tell me where it's lacking. – DinoM Jul 05 '17 at 22:53
  • 1
    Hey @DinoM what does it mean UserCredentialsInputControl? i'm getting type reference missing.. perhaps it might because of i am using it in .net core. could you please ensure it. – David Silwal Jul 14 '20 at 10:55
1

depending on your understanding of mvvm (in my way code behind is allowed in some cases)

so i create a PasswordBox and also a named TextBlock

Xaml

<PasswordBox Height="23" Width="156" PasswordChar="*" PasswordChanged="pwBoxUser_PasswordChanged"/>
<TextBlock Height="1" Width="1" Name="MD5pw" Text="{Binding Passwort, UpdateSourceTrigger=PropertyChanged, Mode=OneWayToSource}" VerticalAlignment="Top" />

codebehind

    private void pwBoxUser_PasswordChanged(object sender, RoutedEventArgs e)
    {
        var pBox =sender as PasswordBox;
        string blank=pBox.Password;

        //to crypt my blank Password
        var sMD5 = myMD5.toMD5(blank); //implement your crypt logic here
        blank ="";

        MD5pw.Text = sMD5;
    }

like you can see your password is save and you can easy bind to it

WiiMaxx
  • 5,322
  • 8
  • 51
  • 89
  • So you now have a plain text password in `PasswordBoxEdit` and an encrypted one in your `TextBlock`. How does that make things safer? – ProfK Nov 09 '13 at 06:36
  • it doesn't and it also doesn't make thinks worse, you can bind to it and you don't need to hand over your `PasswordBox` which is more MVVM than Rachel's version but it all still depends on you both solutions work and both are safe – WiiMaxx Nov 11 '13 at 07:22
  • Yes, excuse me please. I'm new to WPF and I didn't know `Password` wouldn't bind because it's not a dependency property. – ProfK Nov 11 '13 at 11:35
0

Leaving that article aside - there are a few other posts related to this particular question. You can achieve binding using attached properties. Please see:

  1. I believe this question is a duplicate of PasswordBox Binding
  2. The above post points to - http://www.wpftutorial.net/PasswordBox.html
Community
  • 1
  • 1
0

IMO the solution proposed by DinoM above is the more elegant solution and much more understandable than the 'Passwordhelper' class utilised in both the links provide by Chandramouleswaran Ravichandra above (But all credit to Samuel Jack for coming up with it in his blog http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html )

To those who couldn't get DinoM's solution to work because of the missing 'UserCredentialsInputControl' type, just change this parameter to typeof(PasswordUserControl) and it will work.

SingletonSean has a video on his Youtube channel entitled;

Binding to a PasswordBox (MVVM) - EASY WPF (.NET CORE) ( https://www.youtube.com/watch?v=G9niOcc5ssw )

This is the best source I have found in terms of being a complete example, except that he uses string instead of SecureString for the base type of the PasswordProperty but that's easily fixable. He also provides a link to the video's source code in his GitHub repo.

Willie
  • 11
  • 4