Get windows user logged C# ASP - c#

I try with a lot of options to get the current user logged in Windows.
I have the network user with this.
HttpContext.Current.User.Identity.Name
I haven't user login forms and I dont want put this in my proyect because I dont need this.
With
Environment.UserName
I have this ="ASP.NET V4.0 Integrated"
I'm trying to get the current user with this code, but I have an object with 4 users, 2 Administrator, an invited user and my current user, but I dont find something to difference between this.
SelectQuery sQwuery = new SelectQuery("Win32_UserAccount", "Domain='" + System.Environment.MachineName + "'");
ManagementObjectSearcher mSearcher = new ManagementObjectSearcher(sQwuery);
foreach (ManagementObject mObject in mSearcher.Get())
{
var users= mObject;
}
Those are my 4 users
base = {\\DOOKU\root\cimv2:Win32_UserAccount.Domain="DOOKU",Name="Administrador"}
+ [1] {\\DOOKU\root\cimv2:Win32_UserAccount.Domain="DOOKU",Name="Administrator"} object {System.Management.ManagementObject}
+ [2] {\\DOOKU\root\cimv2:Win32_UserAccount.Domain="DOOKU",Name="Invitado"} object {System.Management.ManagementObject}
+ [3] {\\DOOKU\root\cimv2:Win32_UserAccount.Domain="DOOKU",Name="MyUser"} object {System.Management.ManagementObject}
I this case I need the last
There is other option to find this?
thanks.

With 'Environment.UserName', you are retrieving the user identity associated with the IIS Application Pool that hosts the IIS application. You want the identity of the authenticated user currently running the site.
If you have Anonymous Access disabled and Windows Authentication enabled on the site, you really should leverage
HttpContext.Current.User.Identity.Name
to get the name associated with the user running your application. I note in your original post that you 'don't need that,' but for what I'm understanding to be your requirements, I think you do. The current HTTP context holds the user identity.

Related

How to integrate LDAP in WPF application that consumes WCF service

I will start by describing how my application works today without LDAP.
I have WPF application that consumes WCF services (authentication windows or UserName depends on users choice). This services allows communication with database.
I display to user a "Login screen" in order to allow him set her "user name" and "password" then application connects to service and consumes function that checks if UserName and Password exist in database. (see img below)
Now I need also to integrate LDAP for authenticating user accounts against their existing systems instead of having to create another login account.
I'm bit ignorant about LDAP and confused about many things. Please excuse the possible use of wrong terminology.
I googled but I still don't have answers of many questions.
1- What is the relation between users that exist in my database table "User" and profiles that I should be created in LDAP ?
2- What is the check I should do to allow user come from LDAP to access to my application and use all functionnalities of my service ?
3- Should I have service type "LDAP" like other authentications types I have today in my application ("Windows" and "UserName") ?
4- If I want to update my application architecture described in picture above where should I add LDAP ?
First I am going to answer your questions one by one,
The user on LDAP is the same on DB, you can hold LDAP's Username and it's domain in your Users Table,
but the profile on the LDAP may vary with your profile table, but it can be fetched from LDAP address.
It's enough to check username and password over LDAP, just need to hold LDAP addresses in a Table (example ExternalPath) and make a relation between User and ExternalPath tables. LDAP address is contains some specifications.
Yes, you have to have a separate mechanism for identifying LDAP Users which I will explain more further.
This is not hard if everything be atomic and designed right, in further steps you may see it is easy.
So let me tell about my experience in LDAP and Authenticate users on LDAP and DB and our architecture.
I was implemented a WCF service named Auth.svc, this service contains a method named AuthenticateAndAuthorizeUser this is transparent for user which came from LDAP or anywhere.
I hope you get the clue and architecture to Authenticate user over LDAP and DB in below steps:
1- First I have a table named Users which hold users info and one more field named ExternalPath as foreign key, if it is null specify UserName is in DB wit it's password otherwise it is came from UserDirectory.
2- In second step you have to hold LDAP address (in my case LDAP addresses are in ExternalPath table), all LDAP addresses are on port 389 commonly.
3- Implementing authenticate User, if is not found(with Username and Password) then check it's ExternalPath to verify over LDAP address.
4- The DB schema should be something like below screenshot.
As you can see ExternalPath field specify user is from LDAP or not.
5- In presentation layer I am defining LDAP servers like below screenshot also
6- In the other side while adding new user in system you can define LDAP for user in my case I am listing LDAP titles in a DropDown in adding User form (if admin select LDAP address then don't need to get password and save it in DB), as I mentioned just need to hold LDAP username not password.
7- But last thing is authenticating user on LDAP and DB.
So the authenticate method is something like:
User userLogin = User.Login<User>(username, password, ConnectionString, LogFile);
if (userLogin != null)
return InitiateToken(userLogin, sourceApp, sourceAddress, userIpAddress);
else//Check it's LDAP path
{
User user = new User(ConnectionString, LogFile).GetUser(username);
if (user != null && user.ExternalPath != null)
{
LDAPSpecification spec = new LDAPSpecification
{
UserName = username,
Password = password,
Path = user.ExternalPath.Path,
Domain = user.ExternalPath.Domain
};
bool isAthenticatedOnLDAP = LDAPAuthenticateUser(spec);
}
}
If userLogin does not exist in DB by entered UserName and Password then we should authenticate it over related LDAP address.
In else block find User from Users table and get it's ExternalPath if this field was not null means User is on LDAP.
8- The LDAPAuthenticateUser method is :
public bool LDAPAuthenticateUser(LDAPSpecification spec)
{
string pathDomain = string.Format("LDAP://{0}", spec.Path);
if (!string.IsNullOrEmpty(spec.Domain))
pathDomain += string.Format("/{0}", spec.Domain);
DirectoryEntry entry = new DirectoryEntry(pathDomain, spec.UserName, spec.Password, AuthenticationTypes.Secure);
try
{
//Bind to the native AdsObject to force authentication.
object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + spec.UserName + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
if (null == result)
{
return false;
}
}
catch (Exception ex)
{
Logging.Log(LoggingMode.Error, "Error authenticating user on LDAP , PATH:{0} , UserName:{1}, EXP:{2}", pathDomain, spec.UserName, ex.ToString());
return false;
}
return true;
}
If exception raised in LDAPAuthenticateUser means User does not exist in User Directory.
The authentication code accepts a domain, a user name, a password, and a path to the tree in the Active Directory.
The above code uses the LDAP directory provider the authenticate method calls LDAPAuthenticateUser and passes in the credentials that are collected from the user. Then, a DirectoryEntry object is created with the path to the directory tree, the user name, and the password. The DirectoryEntry object tries to force the AdsObject binding by obtaining the NativeObject property. If this succeeds, the CN attribute for the user is obtained by creating a DirectorySearcher object and by filtering on the SAMAccountName. After the user is authenticated and exception not happened method returns true means user find on given LDAP address.
To see more info about Lightweight Directory Access Protocol and authenticate over it THIS Link can be useful which tells about specification more.
Hope will help you.

How to return the Windows Authenticated username instead of the App Pool user in IIS? [duplicate]

In a forms model, I used to get the current logged-in user by:
Page.CurrentUser
How do I get the current user inside a controller class in ASP.NET MVC?
If you need to get the user from within the controller, use the User property of Controller. If you need it from the view, I would populate what you specifically need in the ViewData, or you could just call User as I think it's a property of ViewPage.
I found that User works, that is, User.Identity.Name or User.IsInRole("Administrator").
Try HttpContext.Current.User.
Public Shared Property Current() As
System.Web.HttpContext
Member of System.Web.HttpContext
Summary:
Gets or sets the System.Web.HttpContext object for the current HTTP request.
Return Values:
The System.Web.HttpContext for the current
HTTP request
You can get the name of the user in ASP.NET MVC4 like this:
System.Web.HttpContext.Current.User.Identity.Name
I realize this is really old, but I'm just getting started with ASP.NET MVC, so I thought I'd stick my two cents in:
Request.IsAuthenticated tells you if the user is authenticated.
Page.User.Identity gives you the identity of the logged-in user.
I use:
Membership.GetUser().UserName
I am not sure this will work in ASP.NET MVC, but it's worth a shot :)
getting logged in username: System.Web.HttpContext.Current.User.Identity.Name
UserName with:
User.Identity.Name
But if you need to get just the ID, you can use:
using Microsoft.AspNet.Identity;
So, you can get directly the User ID:
User.Identity.GetUserId();
In order to reference a user ID created using simple authentication built into ASP.NET MVC 4 in a controller for filtering purposes (which is helpful if you are using database first and Entity Framework 5 to generate code-first bindings and your tables are structured so that a foreign key to the userID is used), you can use
WebSecurity.CurrentUserId
once you add a using statement
using System.Web.Security;
We can use following code to get the current logged in User in ASP.Net MVC:
var user= System.Web.HttpContext.Current.User.Identity.GetUserName();
Also
var userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name; //will give 'Domain//UserName'
Environment.UserName - Will Display format : 'Username'
This page could be what you looking for:
Using Page.User.Identity.Name in MVC3
You just need User.Identity.Name.
Use System.Security.Principal.WindowsIdentity.GetCurrent().Name.
This will get the current logged-in Windows user.
For what it's worth, in ASP.NET MVC 3 you can just use User which returns the user for the current request.
If you are inside your login page, in LoginUser_LoggedIn event for instance, Current.User.Identity.Name will return an empty value, so you have to use yourLoginControlName.UserName property.
MembershipUser u = Membership.GetUser(LoginUser.UserName);
You can use following code:
Request.LogonUserIdentity.Name;
IPrincipal currentUser = HttpContext.Current.User;
bool writeEnable = currentUser.IsInRole("Administrator") ||
...
currentUser.IsInRole("Operator");
var ticket = FormsAuthentication.Decrypt(
HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName].Value);
if (ticket.Expired)
{
throw new InvalidOperationException("Ticket expired.");
}
IPrincipal user = (System.Security.Principal.IPrincipal) new RolePrincipal(new FormsIdentity(ticket));
If you happen to be working in Active Directory on an intranet, here are some tips:
(Windows Server 2012)
Running anything that talks to AD on a web server requires a bunch of changes and patience. Since when running on a web server vs. local IIS/IIS Express it runs in the AppPool's identity so, you have to set it up to impersonate whoever hits the site.
How to get the current logged-in user in an active directory when your ASP.NET MVC application is running on a web server inside the network:
// Find currently logged in user
UserPrincipal adUser = null;
using (HostingEnvironment.Impersonate())
{
var userContext = System.Web.HttpContext.Current.User.Identity;
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, ConfigurationManager.AppSettings["AllowedDomain"], null,
ContextOptions.Negotiate | ContextOptions.SecureSocketLayer);
adUser = UserPrincipal.FindByIdentity(ctx, userContext.Name);
}
//Then work with 'adUser' from here...
You must wrap any calls having to do with 'active directory context' in the following so it's acting as the hosting environment to get the AD information:
using (HostingEnvironment.Impersonate()){ ... }
You must also have impersonate set to true in your web.config:
<system.web>
<identity impersonate="true" />
You must have Windows authentication on in web.config:
<authentication mode="Windows" />
In Asp.net Mvc Identity 2,You can get the current user name by:
var username = System.Web.HttpContext.Current.User.Identity.Name;
In the IIS Manager, under Authentication, disable:
1) Anonymous Authentication
2) Forms Authentication
Then add the following to your controller, to handle testing versus server deployment:
string sUserName = null;
string url = Request.Url.ToString();
if (url.Contains("localhost"))
sUserName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
else
sUserName = User.Identity.Name;
If any one still reading this then, to access in cshtml file I used in following way.
<li>Hello #User.Identity.Name</li>

ASP.NET loses user context when connecting to database

In ASP.NET, we have an application that prompts users for their AD credentials using Basic Authentication and ASP.NET Impersonation.
The application then connects to SQL Server with the following connection string
SqlClient.SqlConnection cnn = new SqlClient.SqlConnection();
cnn.ConnectionString =
"Server=" + MenuServer + ";" +
"Database= " + MenuDatabase + ";" +
"Trusted_Connection=Yes;" +
"Pooling = False;";
cnn.Open();
99% of the time, this passes along the user context just fine, but sporadically we get the following error from SQL Server:
Login failed for user 'WebServerName$'. Reason: Could not find a login matching the name provided
Meaning that it has been unable to pass along the user credentials and instead defaulted to the IIS worker process. Interestingly, when we catch the error, the current user will still be accurately recorded with the following code:
string userName = Environment.UserName;
Questions:
What user context does the Integrated Security pass along to the database?
Is it possible to programmatically check the user before calling cnn.Open() to confirm we have a real user?
This can happen if you are using ORM Mappers, e.g. Entity Framework or NHibernate (I have experuienced this with NHibernate). It is because the mapping framework uses Lazy Evaluation: it doesn't get all the data from the database until you ask for it. For example, if you are getting a list of objects each of which contains a further list of objects (e.g. Customer contains a list of Invoice), it won't get the Invoice objects until you actually use them.
If you don't use then until binding them to an aspx control and you do that in the aspx page (not in e.g. the PageLoad event), then the life-cycle of an aspx page means that it looks at the sub-list after your code has run and any impersonation you are doing has ended - this under the IIS account.
You can prevent this happening by either preventing lazy evaluation (generally not a good idea), or by making sure that you touch each of the lists you'll need the page to use in your code, under your impersonated account.
for each (Customer c in customers)
{
int i = c.Invoices.Count; // make sure that they do get retrieved.
}

How to tell if SPUser is Active Directory account

I'm working on a project where the client wants to restrict some content to only Active Directory users . Is there any way to identify that a SPUser is an AD user short of parsing the username string for the domain (or something along those lines). Something like SPUser.IsADUser would be awesome.
Edit
This seems to work, but I'm not sure if this is reliable enough? For this use case, identifying that a user is a windows user is enough (there are no local system accounts)
SPUser user = SPContext.Current.Web.CurrentUser;
string userName = user.LoginName.Substring(user.LoginName.IndexOf('|') + 1);
SPPrincipalInfo info = SPUtility.ResolveWindowsPrincipal(SPContext.Current.Site.WebApplication, userName, SPPrincipalType.User, false);
if(info != null){
//THIS IS A WINDOWS ACCOUNT
}
In my experience it is much better to use audiences for this purpose. You then can easily trim any web part using "Audience" property. You can read about audiences here. Of course it will only work if you have user profile synchronization configured.

Force local user to change password at next login with C#

I'm writing a function for a web app in ASP.NET where the client logs into the server machine, which is Windows authenticated against the local users on the server. The function I am writing resets the users password and emails them the new one. I do this like so:
String userPath = "WinNT://" + Environment.MachineName + "/" + username.Text;
DirectoryEntry de = new DirectoryEntry(userPath);
de.Invoke("SetPassword", new object[] { password });
How can I also check the flag to force the user to change their password the next time they log in with the password emailed to them? I tried using pwdLastSet like so:
de.Properties["pwdLastSet"].Value = 0;
But this apparently only works with LDAP, not WinNT, and I am doing this locally.
Any experts know any better than me? I have even tried looking for a way to do this through the command line so that I can just create a Process, but I haven't been able to find a way to do it that way, either.
For WinNT, you must set the value to 1 rather than 0, and the property name is "PasswordExpired" rather than "pwdLastSet"; see http://msdn.microsoft.com/en-us/library/aa746542(VS.85).aspx
In other words, do this for WinNT:
de.Properties["PasswordExpired"].Value = 1;
(It is confusing, I know, but for LDAP you need to set the property "pwdLastSet" to 0. How's that for inconsistency!)

Categories