4

I am using C# and .Net Framework 4.

I am looking for a foolproof method to get the login id of the currently logged in windows user that is not susceptible to impersonation or hacking. I am looking for this in the form of: DOMAINNAME\USERNAME

e.g. SOMEDOMAIN\JohnDoe

Currently the best I have is:

var identity = System.Security.Principal.WindowsIdentity.GetCurrent();
var currentLoginId = identity.Name;

Is this open to impersonation (outside of someone knowing both the username and password) and if so is there a better way of doing this?

Steve
  • 2,073
  • 4
  • 27
  • 39
  • 'not susceptible to impersonation or hacking' - you can't hack the logged on user without knowing their password. If you know the password I don't think it counts as hacking. – Tim Robinson Aug 17 '10 at 10:42
  • @Tim agree with you on that point. If they know the username and password they can log into windows as that user. – Steve Aug 17 '10 at 10:45
  • In which case, why do you want to avoid impersonation? – Tim Robinson Aug 17 '10 at 10:47
  • The scenario I'm trying to avoid is someone writing code to impersonate another user's identity as I want to use this as part of a "single sign-on" solution. Therefore I need to trust that current WindowsIdentity is who it says it is. If WindowsIdentity reports the current user is SomeDomain\JohnDoe I'll do a database lookup to find an application user called John.Doe who is associated with SomeDomain\JohnDoe and sign them in with asking for a password. – Steve Aug 17 '10 at 13:27
  • I have a long response which I ended up adding to my original answer – Tim Robinson Aug 17 '10 at 15:38

2 Answers2

4

There can be at least four different identities involved at this point:

  1. The identity assigned to the thread
  2. The identity assigned to the process
  3. The account of the user who started the process
  4. The account of the user who logged onto the PC

In your code you're getting (1). This is normally fine, and is usually the same as (2).

To retrieve (2), you could:

  1. Call WindowsIdentity.GetCurrent to get the impersonated identity
  2. Undo impersonation by calling the Win32 RevertToSelf function
  3. Look at WindowsIdentity.GetCurrent to get the underlying process identity
  4. Reset the thread identity by impersonating the identity from step (1)

(2) and (3) will be the same unless you've written unmanaged code that changes the process identity. As @Daniel points out, (3) and (4) could legitimately be different in the presence of the Windows "run as" command.

Edit: You can trust that the current WindowsIdentity is who it says it is, insofar as you can trust any given piece of data in your application.

You could spoof it by attaching a debugger to your process and faking the return value from this call, but if you're going to do that, you might as well fake the piece of code where you pass the user name to the database.

The 100% safe way to do this is to use integrated authentication/SSPI to connect to the database.

Tim Robinson
  • 53,480
  • 10
  • 121
  • 138
1

Only a partial answer:

I believe System.Security.Principal.WindowsIdentity.GetCurrent(); will return the windows user account associaed with the currently executing thread. If the thread or application was started under a different user account from the logged in user, you won't get what you're after using this.

If you can be sure that your aplication was not started using the "run-as" feature (or programatic equialent) and you're not doing anything internally with respect to the thread's identity, you can probably be sure this is the logged in user's account but I'm not 100% on this.

It may be possible to find the user account associated with the widows "session" within which the application is running by using ADSI (see System.DirectoryServices).

Daniel Renshaw
  • 33,729
  • 8
  • 75
  • 94
  • 1
    *"I believe `System.Security.Principal.WindowsIdentity.GetCurrent();` will return the windows user account associaed with the currently executing thread."* I don't think so (see `Thread.CurrentPrincipal`, but it may not be set). Re "RunAs", `WindowsIdentity.GetCurrent()` will give you the "RunAs" user, not the logged-in user. – T.J. Crowder Nov 06 '15 at 10:12