My blog about application development on the .NET platform and Windows®.

Custom authorization in WPF

This post provides a code sample on how to implement your own custom authentication and authorization in a WPF application by implementing classes that derive from the IIdentity and IPrincipal interfaces and overriding the application thread’s default identity.

It is very common for business applications to provide access to data or resources based on the credentials supplied by the user and these kinds of applications typically check the role of a user and provide access to various resources based on that role. The .NET Framework uses the System.Security.Principal.IIdentity and System.Security.Principal .IPrincipal interfaces as the basis for authentication and authorization and by implementing these fairly simple interfaces you can apply your own custom authentication in your applications.

The sample code in this post uses the MVVM design pattern and the solution consists of a simple window with basic login and logout functionality and some buttons to display windows protected with the PrincipalPermissionAttribute, a simple authentication service class to authenticate users based on a supplied username and a password, the actual implementation of the interfaces and some additional helper classes and interfaces.

To get started, create a new WPF application in Visual Studio (File->New->Project), remove the automatically generated MainWindow.xaml, add a new class (Project->Add class) called CustomIdentity and implement it as below.

using System.Security.Principal;

namespace WpfApplication
{
  public class CustomIdentity : IIdentity
  {
      public CustomIdentity(string name, string email, string[] roles)
      {
          Name = name;
          Email = email;
          Roles = roles;
      }

      public string Name { get; private set; }
      public string Email { get; private set; }
      public string[] Roles { get; private set; }

      #region IIdentity Members
      public string AuthenticationType { get { return "Custom authentication"; } }

      public bool IsAuthenticated { get { return !string.IsNullOrEmpty(Name); } }
    #endregion
  }
}

The IIdentity interface encapsulates a user’s identity and the custom implementation above exposes three properties – Name, Email and Roles – to be passed to the constructor when an instance is created. Note that the implementation of the IIdentity.IsAuthenticated property means that a user is considered to be authenticated once the name property has been set.

Next, we add an additional class called AnonymousIdentity that extends CustomIdentity to represent an unauthenticated user, i.e. a user with an empty name.

namespace WpfApplication
{
    public class AnonymousIdentity : CustomIdentity
    {
        public AnonymousIdentity()
            : base(string.Empty, string.Empty, new string[] { })
        { }
    }
}

Once we have the CustomIdentity class we need to implement a class that derives from IPrincipal why we add a new class called CustomPrincipal to the application.

using System.Linq;
using System.Security.Principal;

namespace WpfApplication
{
  public class CustomPrincipal : IPrincipal
  {
    private CustomIdentity _identity;

    public CustomIdentity Identity
    {
        get { return _identity ?? new AnonymousIdentity(); }
        set { _identity = value; }
    }
    
    #region IPrincipal Members
    IIdentity IPrincipal.Identity
    {
        get { return this.Identity; } 
    }

    public bool IsInRole(string role)
    {
        return _identity.Roles.Contains(role);
    }
    #endregion
  }
}

A principal has an identity associated with it and returns instances of this through the IPrincipal.Identity property. In the custom implementation above we provide our own Identity property to be able to set the principal’s identity to an instance of our CustomIdentity class. Note that until the property has been set, i.e. as long as the private member variable _identity is NULL, it will return an anonymous (unauthenticated) identity.

To be able to authenticate users we then add a simple AuthentationService class, along with an interface and a type for the return data, to validate credentials supplied by users. In a real world scenario you would probably store the credentials and any additional information associated with a user in a SQL Server database or some other persistent storage but in the demo sample implementation below the values are stored in a static list inside the class.

using System.Linq;
using System.Text;
using System.Security.Cryptography;

namespace WpfApplication
{
    public interface IAuthenticationService
    {
        User AuthenticateUser(string username, string password);
    }

    public class AuthenticationService : IAuthenticationService
    {
        private class InternalUserData
        {
            public InternalUserData(string username, string email, string hashedPassword, string[] roles)
            {
                Username = username;
                Email = email;
                HashedPassword = hashedPassword;
                Roles = roles;
            }
            public string Username
            {
                get;
                private set;
            }

            public string Email
            {
                get;
                private set;
            }

            public string HashedPassword
            {
                get;
                private set;
            }

            public string[] Roles
            {
                get;
                private set;
            }
        }

        private static readonly List<InternalUserData> _users = new List<InternalUserData>() 
        { 
            new InternalUserData("Mark", "mark@company.com", 
            "MB5PYIsbI2YzCUe34Q5ZU2VferIoI4Ttd+ydolWV0OE=", new string[] { "Administrators" }), 
            new InternalUserData("John", "john@company.com", 
            "hMaLizwzOQ5LeOnMuj+C6W75Zl5CXXYbwDSHWW9ZOXc=", new string[] { })
        };

        public User AuthenticateUser(string username, string clearTextPassword)
        {
            InternalUserData userData = _users.FirstOrDefault(u => u.Username.Equals(username) 
                && u.HashedPassword.Equals(CalculateHash(clearTextPassword, u.Username)));
            if (userData == null)
                throw new UnauthorizedAccessException("Access denied. Please provide some valid credentials.");

            return new User(userData.Username, userData.Email, userData.Roles);
        }

        private string CalculateHash(string clearTextPassword, string salt)
        {
            // Convert the salted password to a byte array
            byte[] saltedHashBytes = Encoding.UTF8.GetBytes(clearTextPassword + salt);
            // Use the hash algorithm to calculate the hash
            HashAlgorithm algorithm = new SHA256Managed();
            byte[] hash = algorithm.ComputeHash(saltedHashBytes);
            // Return the hash as a base64 encoded string to be compared to the stored password
            return Convert.ToBase64String(hash);
        }
    }

    public class User
    {
        public User(string username, string email, string[] roles)
        {
            Username = username;
            Email = email;
            Roles = roles;
        }
        public string Username
        {
            get;
            set;
        }

        public string Email
        {
            get;
            set;
        }

        public string[] Roles
        {
            get;
            set;
        }
    }
}

As it’s considered a bad practice to store passwords in clear text for security reasons, each instance of the InternalUserData helper class contains a one-way hashed and salted password with both users in the sample code having a valid password identical to their username, e.g. Mark’s password is “Mark” and John’s is “John”. The private helper method “CalulcateHash” is used to hash the user supplied password before it’s compared to the one stored in the private list.

The next step is to implement the viewmodel to expose the authentication service to the yet to be implemented login window. We add a new class called AuthenticationViewModel and implement it as below.

using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Controls;
using System.Security;

namespace WpfApplication
{
  public interface IViewModel { }

  public class AuthenticationViewModel : IViewModel, INotifyPropertyChanged
  {
    private readonly IAuthenticationService _authenticationService;
    private readonly DelegateCommand _loginCommand;
    private readonly DelegateCommand _logoutCommand;
    private readonly DelegateCommand _showViewCommand;
    private string _username;
    private string _status;

    public AuthenticationViewModel(IAuthenticationService authenticationService)
    {
        _authenticationService = authenticationService;
        _loginCommand = new DelegateCommand(Login, CanLogin);
        _logoutCommand = new DelegateCommand(Logout, CanLogout);
        _showViewCommand = new DelegateCommand(ShowView, null);
    }

    #region Properties
    public string Username
    {
        get { return _username;}
        set { _username = value; NotifyPropertyChanged("Username"); }
    }

    public string AuthenticatedUser {
        get
        {
            if (IsAuthenticated)
                return string.Format("Signed in as {0}. {1}",
                      Thread.CurrentPrincipal.Identity.Name,
                      Thread.CurrentPrincipal.IsInRole("Administrators") ? "You are an administrator!"
                          : "You are NOT a member of the administrators group.");

            return "Not authenticated!";
        }
    }

    public string Status
    {
        get { return _status; }
        set { _status = value; NotifyPropertyChanged("Status"); }
    }
    #endregion

    #region Commands
    public DelegateCommand LoginCommand { get { return _loginCommand; } }

    public DelegateCommand LogoutCommand { get { return _logoutCommand; } }

    public DelegateCommand ShowViewCommand { get { return _showViewCommand; } }
    #endregion

    private void Login(object parameter)
    {
        PasswordBox passwordBox = parameter as PasswordBox;
        string clearTextPassword = passwordBox.Password;
        try
        {
            //Validate credentials through the authentication service
            User user = _authenticationService.AuthenticateUser(Username, clearTextPassword);

            //Get the current principal object
            CustomPrincipal customPrincipal = Thread.CurrentPrincipal as CustomPrincipal;
            if (customPrincipal == null)
                throw new ArgumentException("The application's default thread principal must be set to a CustomPrincipal object on startup.");

            //Authenticate the user
            customPrincipal.Identity = new CustomIdentity(user.Username, user.Email, user.Roles);

            //Update UI
            NotifyPropertyChanged("AuthenticatedUser");
            NotifyPropertyChanged("IsAuthenticated");
            _loginCommand.RaiseCanExecuteChanged();
            _logoutCommand.RaiseCanExecuteChanged();
            Username = string.Empty; //reset
            passwordBox.Password = string.Empty; //reset
            Status = string.Empty;
        }
        catch (UnauthorizedAccessException)
        {
            Status = "Login failed! Please provide some valid credentials.";
        }
        catch (Exception ex)
        {
            Status = string.Format("ERROR: {0}", ex.Message);
        }
    }

    private bool CanLogin(object parameter)
    {
        return !IsAuthenticated;
    }

    private void Logout(object parameter) {
      CustomPrincipal customPrincipal = Thread.CurrentPrincipal as CustomPrincipal;
      if (customPrincipal != null)
      {
          customPrincipal.Identity = new AnonymousIdentity();
          NotifyPropertyChanged("AuthenticatedUser");
          NotifyPropertyChanged("IsAuthenticated");
          _loginCommand.RaiseCanExecuteChanged();
          _logoutCommand.RaiseCanExecuteChanged();
          Status = string.Empty;
      }
    }

    private bool CanLogout(object parameter)
    {
        return IsAuthenticated;
    }

    public bool IsAuthenticated
    {
        get { return Thread.CurrentPrincipal.Identity.IsAuthenticated; }
    }

    private void ShowView(object parameter) {
        try
        {
            Status = string.Empty;
            IView view;
            if (parameter == null)
                view = new SecretWindow();
            else
                view = new AdminWindow();

            view.Show();
        }
        catch (SecurityException)
        {
            Status = "You are not authorized!";
        }
    }


    #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string propertyName) {
      if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
  }
}

When a user clicks a login button in the view (the window), a command on the viewmodel executes to perform the actual authentication by validating the supplied credentials against our authentication service and, in case of a successful validation, setting the Identity property of the CustomPrincipal instance associated with the currently executing thread to an instance of our CustomIdentity class. For this to work, we must configure our WPF application to use our CustomPrincipal . This is done once when the application starts by overriding the OnStartup method in App.xaml.cs and removing the StartupUri attribute from the XAML.

<Application x:Class="WpfApplication.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>
using System;
using System.Windows;

namespace WpfApplication
{
  /// <summary>
  /// Interaction logic for App.xaml
  /// </summary>
  public partial class App : Application
  {
    protected override void OnStartup(StartupEventArgs e) {
      
      //Create a custom principal with an anonymous identity at startup
      CustomPrincipal customPrincipal = new CustomPrincipal();
      AppDomain.CurrentDomain.SetThreadPrincipal(customPrincipal);
      
      base.OnStartup(e);

      //Show the login view
      AuthenticationViewModel viewModel = new AuthenticationViewModel(new AuthenticationService());
      IView loginWindow = new LoginWindow(viewModel);
      loginWindow.Show();

    }
  }
}

It’s important to note that you must only call AppDomain.CurrentDomain.SetThreadPrincipal once during your application’s lifetime. If you try to call the same method again any time during the execution of the application you will get a PolicyException saying “Default principal object cannot be set twice”. Because of this it is not an option to reset the thread’s principal once its default identity has been initially set.

The DelegateCommand type used for the commands in the viewmodel are a common implementation of System.Windows.Input.ICommand that simply invokes delegates when executing and querying executable status. It doesn’t come with WPF but you can easy implement your own like below or use the one provided by Prism, the framework and guidance for building WPF and Silverlight applications from the Microsoft Patterns and Practices Team.

using System;
using System.Windows.Input;
namespace WpfApplication
{
  public class DelegateCommand : ICommand
  {
    private readonly Predicate<object> _canExecute;
    private readonly Action<object> _execute;

    public event EventHandler CanExecuteChanged;

    public DelegateCommand(Action<object> execute)
      : this(execute, null) {
    }

    public DelegateCommand(Action<object> execute, Predicate<object> canExecute) {
      _execute = execute;
      _canExecute = canExecute;
    }

    public bool CanExecute(object parameter) {
      if (_canExecute == null)
        return true;

      return _canExecute(parameter);
    }

    public void Execute(object parameter) {
      _execute(parameter);
    }

    public void RaiseCanExecuteChanged() {
      if (CanExecuteChanged != null)
        CanExecuteChanged(this, EventArgs.Empty);
    }
  }
}

With this in place, now add a new window called LoginWindow.xaml (Project->Add window) to the application and implement the markup and code-behind as below.

<Window x:Class="WpfApplication.LoginWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="LoginWindow" Height="300" Width="600">
  <Window.Resources>
    <BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter"/>
  </Window.Resources>
    <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto"/>
      <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <TextBlock Text="{Binding AuthenticatedUser}" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
               FontSize="14" HorizontalAlignment="Right" TextWrapping="Wrap" FontWeight="Bold"
               Margin="2,2,2,2"/>
    <TextBlock Text="Username:" Grid.Row="1" Grid.Column="0" />
    <TextBlock Text="Password:" Grid.Row="2" Grid.Column="0" />
    <TextBox Text="{Binding Username}" Grid.Row="1" Grid.Column="1" />
    <PasswordBox x:Name="passwordBox" Grid.Row="2" Grid.Column="1" />
    <StackPanel Orientation="Horizontal" Grid.Row="3" Grid.Column="1">
      <Button Content="Log in" Command="{Binding LoginCommand, Mode=OneTime}"
            CommandParameter="{Binding ElementName=passwordBox}"
            HorizontalAlignment="Center"/>
      <Button Content="Log out" Command="{Binding LogoutCommand, Mode=OneTime}"
            Visibility="{Binding IsAuthenticated, Converter={StaticResource booleanToVisibilityConverter}}"
            HorizontalAlignment="Center" Margin="2,0,0,0"/>
    </StackPanel>
    <TextBlock Text="{Binding Status}" Grid.Row="4" Grid.Column="1"
               HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Red" TextWrapping="Wrap" />
    <StackPanel Grid.Row="5" Grid.Column="1" VerticalAlignment="Center">
      <Button Content="Show secret view" Command="{Binding ShowViewCommand}"
              HorizontalAlignment="Center" />
      <Button Content="Show admin view" Command="{Binding ShowViewCommand}" CommandParameter="Admin"
              HorizontalAlignment="Center" Margin="2,2,0,0" />
    </StackPanel>
  </Grid>
</Window>
using System.Windows;

namespace WpfApplication
{
    public interface IView
    {
        IViewModel ViewModel
        {
            get;
            set;
        }

        void Show();
    }

    /// <summary>
    /// Interaction logic for LoginWindow.xaml
    /// </summary>
    public partial class LoginWindow : Window, IView
    {
        public LoginWindow(AuthenticationViewModel viewModel)
        {
            ViewModel = viewModel;
            InitializeComponent();
        }

        #region IView Members
        public IViewModel ViewModel
        {
            get { return DataContext as IViewModel; }
            set { DataContext = value; }
        }
        #endregion
    }
}

The last step will be to add some protected views to able to verify that the authorization works as expected. The first one, called SecretWindow below, will be accessible by all authenticated users regardless of which group(s) they belong to, i.e. no roles are specified for the PrincipalPermissionAttribute, while the second one will by accessible only for members of the administrator group. Remember that the users and their respective group belongings are defined within the AuthenticationService.

using System.Windows;
using System.Security.Permissions;

namespace WpfApplication
{
  /// <summary>
  /// Interaction logic for SecretWindow.xaml
  /// </summary>
  [PrincipalPermission(SecurityAction.Demand)]
  public partial class SecretWindow : Window, IView
  {
    public SecretWindow() {
      InitializeComponent();
    }

    #region IView Members

    public IViewModel ViewModel {
      get {
        return DataContext as IViewModel;
      }
      set {
        DataContext = value;
      }
    }

    #endregion
  }
}
<Window x:Class="WpfApplication.SecretWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SecretWindow" Height="300" Width="300">
    <Grid>
    <TextBlock Text="This window is only accessible for authenticated users..."/>
  </Grid>
</Window>
using System.Windows;
using System.Security.Permissions;

namespace WpfApplication
{
  /// <summary>
  /// Interaction logic for AdminWindow.xaml
  /// </summary>
  [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
  public partial class AdminWindow : Window, IView
  {
    public AdminWindow() {
      InitializeComponent();
    }

    #region IView Members
    public IViewModel ViewModel {
      get {
        return DataContext as IViewModel;
      }
      set {
        DataContext = value;
      }
    }
    #endregion
  }
}
<Window x:Class="WpfApplication.AdminWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="AdminWindow" Height="300" Width="300">
    <Grid>
    <TextBlock Text="This window is only accessible for admninistrators..."/>
  </Grid>
</Window>

When compiling and running the sample code you will notice that none of the windows will be shown until the user has logged in at the top of the window and only when logged in as “Mark” you will be able to display the administrator window.

Advertisements

38 Comments on “Custom authorization in WPF”

  1. Dan says:

    Code doesn’t work. Did you check this before publishing this article? From where does the class IViewModel coming from ?
    If it work could you please provide the source, probably to SkyDrive

  2. magnusmontin says:

    Hi Dan,

    The IViewModel is just a marker interface for the view model class:

    public interface IViewModel {}

  3. Dan says:

    Thanks. But now I get following errors for all 3 forms which implement IView

    The name ‘InitializeComponent’ does not exist in the current context.

  4. magnusmontin says:

    Forms? You should add three window classes to your solution in Visual Studio by selecting “Add Window” on the project menu: http://msdn.microsoft.com/en-us/library/bb546952(v=vs.90).aspx.

    Then you just open the code-behind file (e.g. LoginWindow.xaml.cs) for each window to modify the partial class to implement the IView interface.

  5. Dan says:

    Yes, I mean Window ( not Form, I am from traditional windows developing background). Yes I Added a new window using Visual Studio, The problem was I cut and paste your code but forget to change namespace in .xaml file to match my project namespace. Now it runs well.
    It would be nice if you update the article to include missing code “public interface IViewModel {}” so the others will have a smooth experience.
    Thanks.

  6. magnusmontin says:

    Thanks for your feedback Dan. I’ve now added the marker interface to the code above the view model class.

  7. Greg says:

    This is exactly the sort of thing I was looking for! Very in-depth and explained well – Thanks for putting it together. I have one question though. Within the explanation and putting a sample together, you predominantly use a window control to use the [PrincipalPermission(SecurityAction.Demand)]. Within my app, I want to prevent a user depending on their role access to certain controls, but I use UserControls. Is there an easy way of means to do this based on your example? I tried to but it ultimately crashes when you navigate to that page.

  8. magnusmontin says:

    Hi Greg,

    To prevent the application from crashing when you try to access a UserControl or a Window that is protected with the PrincipalPermissionAttribute and you are not authorized, you need to catch the SecurityException that is thrown. This is exactly what I am doing in the view model’s ShowView method in the sample code.

  9. dirt says:

    This is a great article! One suggestion I had received when discussing this with others is to replace SHA256Managed() with SHA256Cng() – if not running on WinXP.

  10. ebia says:

    Cannot implicitly convert type ‘WpfApplication.LoginWindow’ to ‘WpfApplication.IView’.
    An explicit conversion exists (are you missing a cast?)

    this Code doesn’t work: loginWindow = new LoginWindow(viewModel);
    how to fix this error?
    Thanks.

    protected override void OnStartup(StartupEventArgs e)
    {

    //Create a custom principal with an anonymous identity at startup
    CustomPrincipal customPrincipal = new CustomPrincipal();
    AppDomain.CurrentDomain.SetThreadPrincipal(customPrincipal);

    base.OnStartup(e);

    //Show the login view
    AuthenticationViewModel viewModel = new AuthenticationViewModel(new AuthenticationService());
    IView loginWindow;
    loginWindow = new LoginWindow(viewModel);
    loginWindow.Show();

    }

  11. ebia: The LoginWindow class must implement the IView interface as shown in the code.

  12. ebia says:

    Thanks Magnus Montin

    Resolved Error when implemented IView to LoginWindow class.

    but when run this project and entry User name:Mark in Username TextBox
    doesn’t work and Reflection
    and dont show AdminWindow

    please Upload To your SkyDrive this Project

  13. soori says:

    I am getting exception… Can you please share the code…?

  14. vichu says:

    I like to display the login screen as popup screen with Shell display in background. it is possible?

  15. Vman says:

    Never Authenticates?

  16. Pastor says:

    Hi, man nice post and description step by step, however it never authenticates, can you revise that?

  17. Great post. I got it working right away. I want to close the login window and add the logout button to a protected form. I am a bit new to MVVM so do I need to add the logout method to each of my ViewModels or should I just make logout public on the AuthenticationViewModel and use it from all my UI?

  18. Dominic says:

    the [PrincipalPermission(SecurityAction.Demand)] is returning an error object reference not set to the instance of an object

  19. Thank you for the article! It worked great for me :)

  20. Yassiel Enrique Oliva Carmona says:

    This is really nice article. Thanks!! :D

  21. Plamen Penchev says:

    Thank you, nice tutorial!

  22. Worked first time for me, excellent. Can I apply this to a database that a new asp.net project has created with users in already?

  23. grisli says:

    Error 1 Inconsistent accessibility: property type ‘WpfApplication1.DelegateCommand’ is less accessible than property ‘WpfApplication1.AuthenticationViewModel.LoginCommand’ c:\users\greez\documents\visual studio 2013\Projects\WpfApplication1\WpfApplication1\AuthenticationViewModel.cs 61 32 WpfApplication1

    I can’t get past this

  24. grisli: You must make the DelegateCommand class public when you expose a public DelegateCommand property from another class:

    public class DelegateCommand : ICommand
    {

    }

  25. Channa says:

    Works great for me, thanks!

  26. thorfalahnur says:

    Thank you so much! I’m not a programmer I just fiddle with c# and VS, got it going with a newb app I made, only stole some parts of your code. Thanks again!

  27. Dave Totzke says:

    >AppDomain.CurrentDomain.SetThreadPrincipal(customPrincipal);

    Thank you! You have no idea how crazy I was getting trying to use Thread.CurrentPrincipal.

  28. hamdi says:

    Thank you! very much

  29. Promise says:

    Thank you :)

  30. Leovel says:

    Excelent Article… thank you! very much

  31. Paco Tena says:

    Thank you very much, I adapted the code to use an abstract class instead of an interface so the code is cleaner when dealing with windows that share this code:

    public IViewModel ViewModel{
    get { return DataContext as IViewModel; }
    set { DataContext = value; }
    }

    Instead I defined an abstract class extending Window native class, so every window extends WindowBase instead of Window:

    public abstract class WindowBase : Window{
    public IViewModel ViewModel
    {
    get { return DataContext as IViewModel; }
    set { DataContext = value; }
    }
    }

    Thanks a lot for this entry!

  32. Vangi says:

    Thanks for sharing, this is exactly what I was looking.

  33. How would you suggest adding new user details? I want to adapt the code to use a local database, so would you suggest to make a separate method to add a user rather than adding to this code?

  34. Nico Travassos says:

    Hi Magnus Montin,

    Wpf has a setting in properties –> services –> Enable User Windows authentication

    Must this be enabled to use windows authentication? and your example above?

  35. Nico Travassos says:

    Hi,

    Visual studio has a option in project [Properties]-[Services]- Enable client application services – Use windows authentication

    Does this need to be checked for your tutorial above or is it only related to MVC

  36. Nico says:

    Hi there where can i find this source code besides this blog? Github?

  37. dan says:

    How can I implement this using PRISM and Unity?

  38. SrustThakkar says:

    How can I retrive UserName and Email from identity?


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s