How can I impersonate logged on user and get access to unc folders? - c#

I'm having trouble impersonating logged on user and then access unc files. I have tried using this sample code:
using System.Security.Principal;
...
// Obtain the authenticated user's Identity
WindowsIdentity winId = (WindowsIdentity)HttpContext.Current.User.Identity;
WindowsImpersonationContext ctx = null;
try
{
// Start impersonating
ctx = winId.Impersonate();
// Now impersonating
// Access resources using the identity of the authenticated user
}
// Prevent exceptions from propagating
catch{}
finally
{
// Revert impersonation
if (ctx != null)
ctx.Undo();
}
// Back to running under the default ASP.NET process identity
If I try to access a file locally where the comment says Access resources using the identity of the authenticated user it works exactly as it should. If I however try to do the same thing with a file on a file server somewhere using UNC like \\ServerName\Share\FileName.txt it doesn't matter that the impersonated account has enough rights. The application throws an exception saying that the ASP.NET account does not have enough rights.
I have also tried to use unmanaged code to perform the impersonation and then it works! Local file or UNC, doesn't matter, works like a charm!
The problem is that you have to provide password and since it is the logged on users rights I want to check I can't provide that.
Does anyone know why the application behaves like this? Is it some configuration setting I need to set?

Web application runs with specific
identity, this identity is based on a
user account on the local machine or
domain.
The application uses this identity
when it accesses resources on disk or
services.
If the account does not have rights to
the resource, the web application will
not be able to use the resource.
Impersonation is where the web
application assumes a different
identity from the default
Impersonation can be configured to be
used for the web application on
startup, by adding an tag
to the web.config file. Impersonation
can also be implemented dynamically in
code, so that it can be turned on and
off as needed.
From ASP.NET Identity and Impersonation
So check you web.config and IIS Configuration and ensure that you're impersonating the correct user.

Related

ASP.Net MVC - OWIN - Allowing Windows/Individual Authentication

I have an ASP.Net MVC 5 application which is currently using individual authentication (account/login.cshtml page with no authentication/anonymous access) and OWIN. Works fine.
As this is an intranet app I want to allow the users to log in under their windows account, another users windows account or an application account(admin, special user etc. - these accounts have no associated domain account).
For the first option I wanted to display their windows username on the login screen and they can simply click the "ok" button to login. To get the username I modified the Visual Studio Project properties to disable anonymous authentication and enable windows authentication. Also modified the web.config and set the authentication mode to Forms. This causes "HTTP Error 404.15 - Not Found". This appears to be due to an authentication loop caused by OWIN with the following suggestions to fix:
Ensure Login controller methods allow anonymous access (seems to be this way by default).
or Modify Startup.auth, comment out the LoginPath property.
or Modify the web.config, add the appSetting "owin:AutomaticAppStartup" with value "false".
I opted for the LoginPath fix and this appears to work (as does web.config change) in that there are no errors and the login page displays with the windows username (retrieved using System.Threading.Thread.Currentprinciple.Identity.Name).
The problem is now that once the user has logged in the OwinContext has no user ( HttpContext.GetOwinContext().GetUserManager()).
Ideally I don't need IIS or OWIN doing any authentication as it's done by the app - but I need the initial request (for the account/login page) to include the Authenticate headers so I can get the windows user.
Firstly I would like to understand what causes the "HTTP Error 404.15" and fix.
Secondly, how do I get OWIN to work with the authentication change - I just need it to persist the user for controller authentication.
This is just a guess but I believe the error is caused by the misconfiguration you've described: you have set the authentication mode to "Forms" but set the project to use Windows Authentication. It can be confusing but Windows Authentication is not Forms Authentication. When you are using Forms Authentication the user provides the credentials in the form that is submitted, validated (including all anti-forgery goodness) against the user store (I believe you are using ASP.NET Identity which would be a default for "Individual Authentication" setting) and if the validation is successful a cookie to set is included in the response. This cookie is then used to authenticate further requests.
As confirmed by Katana documentation, there is no built-in middleware for Windows Authentication - Microsoft simply assumes that IIS should be used for that. Which effectively prevents us from easily combining Katana OWIN middleware providers with Windows authentication. Now, easily is the key word: we still can "hack" our way around it.
Unfortunately, it still will be a hack: I have not found a way to make the authentication "transparent" (as in "a user opens the login form and can enter both the AD account credentials or the individual account credentials and everything just works"). You will need to maintain the individual account record for every Windows user (as you would do with any external OWIN middleware, such as Google or Facebook). You can automate the account creation and association though and make it look transparent. You can add an "external provider" button for your Windows authentication.
Authenticating the user would look like (in a separate "AD Authentication" controller):
bool userWindowsAuthentication = Request.LogonUserIdentity.IsAuthenticated;
if (userWindowsAuthentication) {
var userStoreDatabaseContext = new ApplicationDbContext();
var userStore = new UserStore<UserModel>(userStoreDatabaseContext);
var userStoreManager = new UserManager<UserModel>(userStore);
var userWindowsLoginCredentials = GetWindowsLoginInfo();
var existingInternalUser = userStoreManager.FindAsync(userWindowsLoginCredentials.UserName)
if (existingInternalUser) {
// It means that the user already exists in the internal provider and here you simply authenticate and redirect to destination
} else {
// It means that the user does not exist. You can automatically create the internal user record here and associate the Windows user with the internal record.
}
} else {
// It means that user is not signed in using Windows authentication, so you either want to redirect back to the login page or restrict access or do something else
}
As you can see, it's "dirty". Another hack: you can have additional layer (separate application or a virtual application) that accepts only Windows authentication. This app can be your log-in resource. If the user is authenticated with Windows AD you can redirect them to the correct login page. You can go even further and add their login info in the redirect request header but if you do so - the header must be encrypted to ensure that Windows authentication cannot be faked and the only thing that should be able to decrypt and validate it should be your main application. Again, dirty, but works.

How to access SQL-DB as AppPool when running ASP.NET Impersonation OR How to get the NT-User when running AnonymousAuthentication

The tools
myWebApp: ASP.NET Core 1.1 MVC
myAuthApp with IdentityServer4
MS SQL Server 2012
IIS 8 on Win2012 Server
What we Want:
figure out what NTUser (intranet) is using the app to get userinfo from sqlserver-db (by searching the NTUserName) without any login dialog
What we have
one website (WinAuthApp) using asp.net impersonation (IIS Authentication) only to deliver NTUser-Name with return User.Identity.Name
and one website (our WebAPP) with Anonymous Authentication to get access to SQLServer with AppPool Identity. This WebApp redirects (when requesting without authentication token) to our AuthApp to check identity. AuthApp asks the WinAuthApp for the username and searchs the DB for permissionflags and builds an identity and a generates a token for it. with this authentication token it returns to WebApp and is now authenticaticated. External users give Name and Passwort and get a token to access WebApp.
Problems with this approach
when external users come to webApp and AuthApp asks WinAuthApp (with WindowsAuthentication configured) they get the NT-Login screen instead of WebApp's "Login Page for Externals". One contraint is: the intranetuser should NOT get a login dialog. (webApp has to answer to links and open the requested page immediately).
Summary
How can i configure my AuthApp (IdentityServer4) to have access to current NTUser (IF request comes from Intranet) but mainly working as AppPool-Identity (esp. for DB-Access)
I figured it out:
in Web.config set forwardWindowsAuthToken="true", and then set WindowsAuthentication true and asp.net impersonation false.
Then access to SQL-Server is done with appPool-Acount, and in the application context.User.Identity.Name gives user's NT-Account.
It wasn't too difficult but i always set WinAuth AND Impersonation synced. Don't know why.

Why might UserPrincipal.GetAuthorizationGroups() fail for one principal but not another?

I am running the following code in an ASP.Net MVC website:
using (var ctx = new PrincipalContext(ContextType.Domain, DOMAIN))
using (var userPrincipal = UserPrincipal.FindByIdentity(ctx, principal.Identity.Name))
using (var groups = userPrincipal.GetAuthorizationGroups())
The code is used a custom RoleProvider and the variable "principal" is HttpContext.Current.User. DOMAIN is my local domain.
This code works fine when I log in to the site, but throws an exception on the last line if I log in as either of a couple of test users.
While trying to retrieve the authorization groups, an error (5) occurred.
The test users have fewer permissions on the domain but are users in active directory. I tried creating the PrincipalContext with an alternative constructor supplying my username and password but it didn't make any difference to the behaviour.
This happens both on my dev machine and also on a separate staging server so I don't think it has anything to do with local permissions. I also don't see how it can be related to the users' permissions as I would expect the active directory request to be made as the IIS App Pool user (impersonation is turned off) or perhaps the user specified in the PrincipalContext constructor.
Any suggestions as to what is going on gratefully received.
It's not enough that they are users in Active Directory. The IIS App Pool user needs to be a member of the Windows Authorization Access Group to execute GetAuthorizationGroups.
Answered here: While trying to retrieve the authorization groups, an error (5) occurred

FileNet Api access rights for asp.net

I have some sort of trouble, but i can't figure out where it can be. I have a search method. It uses filenet api and connects to server using admin credentials.
ClientContext.SetProcessCredentials(new UsernameCredentials(login, password));
var connection = Factory.Connection.GetConnection(storeUri);
var domain = Factory.Domain.GetInstance(connection, null);
var store = Factory.ObjectStore.FetchInstance(domain, storeName, null);
return store;
At target system it works fine, when i run console application. But when i run it at asp.net web site i got
"The requester has insufficient access rights to perform the requested operation." error. Who is requester at this point?
When you're running the application through a console, the user you are logged in as is used i.e. this is you and you probably have admin rights on the machine.
When you run it through IIS, this will depend on which version of IIS you are using. Look at this question for more information. You'll either need to change which user the web site is running under or grant further permissions to the user (or group) that is currently configured.

What are the security permissions required to enumerate users on active directory

System Specs:
Infopath 2007 with c# code-behind
Webservices
Active Directory
I need to get the users name (First Name and Last Name) from active directory but the user appears to not have permissions to read the active directory listings.
What permissions do I need to give the user in order for them to search AD
I am using code like this
SearchResult result;
using (DirectoryEntry de = new DirectoryEntry("LDAP://DC=contoso,DC=com,DC=au"))
{
DirectorySearcher search = new DirectorySearcher(de, (string.Format("(&(objectClass=user)(mailNickname={0}))",this.Application.User.UserName)));
result = search.FindOne();
}
I have considered creating a webservice that gets the information required but that seems like overkill but would get around having to make sure every possible user of the form is required to have the correct permissions
EDIT:
The code that I am trying to execute is infopath code behind. The form itself connects to webservices to retrieve some of its data. as such it is under infopath's security model. The form is fully trusted so it should be fine to execute under the current user context.
My fault for not adding the extra detail.
When you create a new DirectoryEntry without specifying a username and password you're connecting to Active Directory using the credentials of the executing user - in your case probably the local IUSR_...-account on the web server which is the default account used when a new web site is set up in IIS. Because that's a local account you won't be able to access Active Directory.
You have two options:
Create a service account in Active Directory and use that account explicitly, ie DirectoryEntry de = new DirectoryEntry("LDAP://DC=contoso,DC=com,DC=au", "sa-username", "sa-password", AuthenticationTypes.Secure). Of course, passwords in clear text in the code is not a good idea so find a way to encrypt the password.
or
Configure the IIS application pool for your web site (IIS 6+) to run under a domain user account - that way that account is used when connecting to Active Directory.
Any user of the AD should have permissions to browse the AD by default.
You probably just need to change your directory entry to point to the user container like so:
new DirectoryEntry("LDAP://CN=users,DC=contoso,DC=com,DC=au")
Your user container could be another name.
If that does not solve the problem it may be that the application is not actually running as the user. For example, an ASP.NET website would need to be using impersonation in order to query the AD.

Categories