using System;
using System.ComponentModel;
using System.Security.Principal;
using static Vanara.PInvoke.AdvApi32;
namespace Vanara.Security.Principal
{
///
/// Impersonation of a user. Allows to execute code under another user context. Please note that the account that instantiates this class
/// needs to have the 'Act as part of operating system' privilege set.
///
public class WindowsLoggedInIdentity : IDisposable, IIdentity
{
private readonly SafeHTOKEN hToken;
private readonly bool ownId = true;
///
/// Provides an identity to a logged into user given the supplied credentials. Please note that the account that instantiates this
/// class needs to have the 'Act as part of operating system' privilege set.
///
///
/// A string that specifies the name of the user. This is the name of the user account to log on to. If you use the user principal
/// name (UPN) format, User@DNSDomainName, the parameter must be NULL.
///
///
/// A string that specifies the name of the domain or server whose account database contains the account.
/// If this parameter is NULL, the user name must be specified in UPN format. If this parameter is ".", the account is validated by
/// using only the local account database.
///
/// A string that specifies the plain-text password for the user account specified by .
///
/// Type of the logon. This parameter can usually be left as the default. For more information, lookup more detail for the
/// dwLogonType parameter of the Windows LogonUser function.
///
///
/// The logon provider. This parameter can usually be left as the default. For more information, lookup more detail for the
/// dwLogonProvider parameter of the Windows LogonUser function.
///
public WindowsLoggedInIdentity(string userName, string domainName, string password, LogonUserType logonType = LogonUserType.LOGON32_LOGON_INTERACTIVE,
LogonUserProvider provider = LogonUserProvider.LOGON32_PROVIDER_DEFAULT)
{
if (string.IsNullOrEmpty(userName)) throw new ArgumentNullException(nameof(userName));
if (string.IsNullOrEmpty(password)) throw new ArgumentNullException(nameof(password));
if (string.IsNullOrEmpty(domainName) && !userName.Contains("@")) throw new ArgumentNullException(nameof(domainName));
if (LogonUser(userName, domainName, password, logonType, provider, out hToken))
{
using (hToken)
{
AuthenticatedIdentity = new WindowsIdentity(hToken.DangerousGetHandle());
}
}
else
throw new Win32Exception();
}
///
/// Starts the impersonation with the given . Please note that the account that instantiates this class
/// needs to have the 'Act as part of operating system' privilege set.
///
/// The identity to impersonate.
public WindowsLoggedInIdentity(WindowsIdentity identityToImpersonate)
{
AuthenticatedIdentity = identityToImpersonate;
ownId = false;
}
/// Gets the authenticated identity.
public WindowsIdentity AuthenticatedIdentity { get; private set; }
/// Gets the type of authentication used.
string IIdentity.AuthenticationType => AuthenticatedIdentity?.AuthenticationType;
/// Gets a value that indicates whether the user has been authenticated.
bool IIdentity.IsAuthenticated => AuthenticatedIdentity?.IsAuthenticated ?? false;
/// Gets the name of the current user.
string IIdentity.Name => AuthenticatedIdentity?.Name;
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
public virtual void Dispose()
{
if (ownId) AuthenticatedIdentity?.Dispose();
hToken?.Dispose();
AuthenticatedIdentity = null;
}
}
}