I have an asp.net web application with forms authentication and users (credentials) are checked against active directory, username is actually samAccountName attribute from AD.
Now I need to enable users to get access to some files which are located on file share, where each user has his own folder.
First proof of concept works like this:
appPool in IIS is configured to run under some domain user, and this user was given R/W access to file share and all user folders
when the user logs into web app only content of the folder on the path "\\myFileServer\username" is visible to him. And same when uploading files they get stored to "\\myFileServer\username".
While this works, doesn't seem to be secure at all. First issue is that user under which application pool runs has access to folders from all users. And even bigger concern is that only username determines to which folder you have access.
So my question is what is the correct/better way to doing this ? I was reading about impersonating the user, but this is not advised anymore if I understood correctly ? And I don't have Windows authentications since the web application must be accessible from internet.
I recommend not running the application under a user account, but creating an application specific account under which it runs with the proper R/W rights, and separate the person who gives these rights from the development team.
Within the application's authentication: after you receive a GET/POST request, you can verify the path to which the current user would read/write data, and cross-reference this with the path the user is authorized to read/write from. If these are incorrect, return a 401 NOT AUTHORIZED response, else, carry on the operation as you do now.
If your endpoints are protected properly, and the application runs under its own account, I don't see any harm in the setup itself. This still however gives the developers a way, through the application, to indirectly access other user's files. Based on how tight these checks must be, you could add additional controls, (like only allowing the application to connect from the production server, and only allowing server transport in a controlled way).
From the Description of your Problem i think Custom HttpHandlers are the right choice for you. You didn't mention what type of files will be present in your Folder , for brevity i will answer by assuming it will be having PDF files.
As you were mentioning that your application will be having different users so for this you need to use .NET built-in authentication manager and role provider. With a simple security framework setup, we'll place a PDF file in the web application, behind a web.config protected folder.then create a custom HTTP handler to restrict access on the static document to only those users who should be allowed to view it.
A sample HTTP Handler:
public class FileProtectionHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
switch (context.Request.HttpMethod)
{
case "GET":
{
// Is the user logged-in?
if (!context.User.Identity.IsAuthenticated)
{
FormsAuthentication.RedirectToLoginPage();
return;
}
string requestedFile =
context.Server.MapPath(context.Request.FilePath);
// Verify the user has access to the User role.
if (context.User.IsInRole("User"))
{
SendContentTypeAndFile(context, requestedFile);
}
else
{
// Deny access, redirect to error page or back to login
//page.
context.Response.Redirect("~/User/AccessDenied.aspx");
}
break;
}
}
}
Method SendContentTypeAndFile :
private HttpContext SendContentTypeAndFile(HttpContext context, String strFile)
{
context.Response.ContentType = GetContentType(strFile);
context.Response.TransmitFile(strFile);
context.Response.End();
return context;
}
private string GetContentType(string filename)
{
// used to set the encoding for the reponse stream
string res = null;
FileInfo fileinfo = new FileInfo(filename);
if (fileinfo.Exists)
{
switch (fileinfo.Extension.Remove(0, 1).ToLower())
{
case "pdf":
{
res = "application/pdf";
break;
}
}
return res;
}
return null;
}
Last step is that you need to configure this HTTP Handler in the webconfig ,
and You can see the more info here
Here is the complete Source Code
You're architecture (and assumptions) seem good for a low/mid security level, but if the nature of your data is very sensitive (medical, etc) my biggest concern about security would be controlling the user sessions.
If you're using forms authentication then you're storing the authenticated identity in a cookie or in a token (or if you're using sticky sessions then you're sending the session Id, but for the case it's the same). The problem arises if user B has phisical access to the machine where user A works. If user A leaves it's workplace (for a while or forever) and he doesn't explicitly close it's session in your web app, then his identity has been left around, at least until his cookie/token expires, and user B can use it since the identity system of ASP.NET hasn't performed a SignOut. The problem is even worse if you use tokens for authorization, because in all the infamous Microsoft implementations of the Identity System you're responsible of providing a way to invalidate such tokens (and make them dissapear from the client machine) when the user signs out, since they would stay valid until it's expiration. This can be addressed (but no completely thus not very satisfactorily for high security requirements) issuing short living refresh tokens, but that's another story, and I don't know if it's your case. If you're going with cookies then when user A signs out it's cookie is invalidated and removed from the request/response cicle, so this problem is mitigated. Anyway you should ensure that your users close their sessions in your web app or/and configure the cookies with short lives or short sliding expirations.
Other security concerns may be related with CSRF, wich you can prevent using the Antiforgery Token infrastructure of ASP.NET, but these kind of attacks are methods that are very far away from the tipical user (I don't know anything about the nature of your user and if your app is exposed to public on internet or it's only accesible on an intranet), but If you worry for such specialised attacks and have so sensitive data, maybe you should go with something more complex than forms authentication (two factor, biometrical, etc)
Related
I have an APP using restful server. I want to store PDF's, images, etc. in folders on my server. How can I make the folders private on server, yet allow App to access only certain folders depending on their app access.
I have different users in app and security/tokens established, etc. But if they upload an image for their avatar (and now PDF's), they get stored in folders on the server, and I just display with image source=https://blahblah.com/org1/images/user232.jpg.
How can I make that not accessible to outside (like just going to browser), yet make accessible to app if they have correct login privilege's for that organization/user? And then further extend that logic to more sensative PDF's, and other docs uploaded through app. I didn't want to store in SQL since then harder to use simple image display tools and I already have upload and media managers using folders structures.
I can see how to secure if logging onto server through browser (credentials), but can't see how you connect App with that security level and maintain it for the session.
For future readers. Most of the work was done on the restful (ASP.NET) side. I first tried using authorization/Authentication in web.config and having Allow and deny. This allowed a redirect of a user to a login page; however, it didn't do it if they entered an image exactly correct on website.
Found HTTPHandlers (adding in webconfig ) where I could write code that would be executed once the user entered the specific Image address xyz/abc/image.png. I found this a bit feeling like a hack.
So lastly modified my
routes.MapRoute(
name: "staticFileRoute",
url: "publicstor/{*file}",
defaults: new { controller = "Home", action = "HandleStatic" }
And add a function like this to home controller.
[System.Web.Http.HttpGet]
public ActionResult HandleStatic(string file)
{
if (Session["OrgId"] == null) //todo need to add full security check.
{
return View("Login");
}
else //Either coming from app or coming from web interface
{
string mimeType = MimeInfo.GetMimeType(Path.GetExtension(file));
return File(file, mimeType);
}
}
The final bit is on the Xamarin side to now pass security when getting an image. Since just a simple Xamarin.Forms.Image doesn't have a way to pass login info or tokens/authentication I used
https://forums.xamarin.com/discussion/145575/image-from-url-needing-auth
And established an appwide webclient that logged in generally once forcing my restful to go through security validation, then just accessed the images/documents through out my app from that webclient. So far so good. Hopefully there are no holes.
This gives the gist to a future reader.
I have an ASP.NET 3.5 application that I recently extended with multiple membership and role providers to "attach" a second application within this application. I do not have direct access to the IIS configuration, so I can't break this off into a separate application directory.
That said, I have successfully separated the logins; however, after I login, I am able to verify the groups the user belongs to through custom role routines, and I am capable of having identical usernames with different passwords for both "applications."
The problem that I am running into is when I create a user with an identical username to the other membership (which uses web.config roles on directories), I am able to switch URLs manually to the other application, and it picks up the username, and loads the roles for that application. Obviously, this is bad, as it allows a user to create a username of someone who has access to the other application, and cross into the other application with the roles of the other user.
How can I mitigate this? If I am limited to one application to work with, with multiple role and membership providers, and the auth cookie stores the username that is apparently transferable, is there anything I can do?
I realize the situation is not ideal, but these are the imposed limitations at the moment.
Example Authentication (upon validation):
FormsAuthentication.SetAuthCookie(usr.UserName, false);
This cookie needs to be based on the user token I suspect, rather than UserName in order to separate the two providers? Is that possible?
Have you tried specifying the applicationName attribute in your membership connection string?
https://msdn.microsoft.com/en-us/library/6e9y4s5t.aspx?f=255&MSPPError=-2147217396
Perhaps not the answer I'd prefer to go with, but I was able to separate the two by having one application use the username for the auth cookie, and the other use the ProviderUserKey (guid). This way the auth cookie would not be recognized from one "application" to the other.
FormsAuthentication.SetAuthCookie(user.ProviderUserKey.ToString(), false);
This required me to handle things a little oddly, but it simply came down to adding some extension methods, and handling a lot of membership utilities through my own class (which I was doing anyhow).
ex. Extension Method:
public static string GetUserName(this IPrincipal ip)
{
return MNMember.MNMembership.GetUser(new Guid(ip.Identity.Name), false).UserName;
}
Where MNMember is a static class, MNMembership is returning the secondary membership provider, and GetUser is the standard function of membership providers.
var validRoles = new List<string>() { "MNExpired", "MNAdmins", "MNUsers" };
var isValidRole = validRoles.Intersect(uroles).Any();
if (isValidRole)
{
var userIsAdmin = uroles.Contains("MNAdmins");
if (isAdmin && !userIsAdmin)
{
Response.Redirect("/MNLogin.aspx");
}
else if (!userIsAdmin && !uroles.Contains("MNUsers"))
{
Response.Redirect("/MNLogin.aspx");
}...
Where isAdmin is checking to see if a subdirectory shows up in the path.
Seems hacky, but also seems to work.
Edit:Now that I'm not using the username as the token, I should be able to go back to using the web.config for directory security, which means the master page hack should be able to be removed. (theoretically?)
Edit 2:Nope - asp.net uses the username auth cookie to resolve the roles specified in the web.config.
I am hosting CassiniDev 4.0 in my windows service running an MVC 3.0 configuration site for my service.
I have the web.config setup to use windows authentication. When I look at the HttpContext.User in the web site, it shows the identity that the service is running under, not the itentity of the user making the request. The User.AuthenticationType is NTLM, which is correct, BTW.
This seems pretty clearly to be a bug, but wanted to run it by the community to see if there is some configuration I am missing.
It seems like it might be a variation on this issue postedlast week:
SecurityIdentifiers in Cassini-dev's NTLM authentication
This is definitely a bug in Cassini Dev. It looks like this method is returning the wrong token: Request.GetUserToken(). The code:
public override IntPtr GetUserToken()
{
return _host.GetProcessToken();
}
And here _host.GetProcessToken() is a pointer to a security token belonging to the user who owns the Cassini process, it is not the token belonging to the user that's logged in. What needs to happen is the NtlmAuth object needs to pass the security token back to the Request object so that it can be returned when this method is called instead of the host's token. Not really sure what the best way to do this is but you can see in the NtlmAuth class, the security token is acquired here:
IntPtr phToken = IntPtr.Zero;
if (Interop.QuerySecurityContextToken(ref _securityContext, ref phToken) != 0)
{
return false;
}
phToken is the security token but it needs to get back to the Request object and not call Interop.CloseHandle(phToken); later in that method, where it frees the token. Note that CloseHandle() needs to be called on the token eventually, otherwise a new one will be issued for every request made by a logged in user but unused ones will never get freed. One possible place to do this is in the Request object, which subclasses SimpleWorkerRequest and you can override the EndOfRequest method to call CloseHandle() on the security token.
I am using database with a list of username/passwords, and a simple web form that allows for users to enter their username/password.
When they submit the page, I simply do a stored procedure check to authenticate. If they are authorised, then their user details (e.g. username, dob, address, company address, other important info) are stored in a custom User object and then in a session. This custom User object that I created is used throughout the web application, and also in a sub-site (session sharing).
My question/problems are:
Is my method of authentication the correct way to do things?
I find users complaining that their session have expired although they "were not idle", possibly due the app pool recycling? They type large amounts of text and find that their session had expired and thus lose all the text typed in. I am uncertain whether the session does really reset sporadically but will Forms Authentication using cookies/cookiless resolve the issue?
Alternatively should I build and store the User Object in a session, cookie or something else instead in order to be more "correct" and avoid cases like in point #2.
If I go down the Forms Authentication route, I believe I cannot store my custom User object in a Forms Authentication cookie so does it mean I would store the UserID and then recreate the user object on every page? Would this not be a huge increase on the server load?
Advice and answers much appreciated.
L
It doesn't really care whether you use your own authentication system, or the default membership providers when using such a simple scenario.
You should avoid using the InProc session state when the app might recycle some times a day. Rather store your session into a database (SqlSessionState) or use a StateServer. Then the application pool can recycle all day without interferring with your sessions. Setting the session timeout to 60 minutes or something, will solve the remaining issues. Never use cookieless sessions (unless you know what you're doing), as they make it way too easy to steal one's session.
Just store it into the session (or profile if you use the default membership provider). Not only is a cookie easily readible, it is also limited to 4 KB.
No, you will have a profile where all the user information is stored. It doesn't really matter whether you use forms authentication or a custom system that stores it's data into SqlSessionState. The membership provider will store the Profile ID into a cookie, same as the session state will save the Session ID into a cookie.
You can use ASP.NET Membership, Roles, Forms Authentication, and Security Resources
I will give an example using c#
For reference Forms Authentication in ASP.NET 2.0
//code for checking user name & password
protected void btnlogin_Click(object sender, EventArgs e)
{
try
{
if (txtUserName.Text.Trim() != "" && txtPassword.Text.Trim() != "")
{
User obj = objUser.UserAuthenticate(txtUserName.Text.Trim(), txtPassword.Text.Trim());
if (obj != null)
{
//To set AuthenticationCookie of usertype "User"
SetAuthenticationCookie("User", obj.UserID.ToString(), obj.DisplayName);
HttpCookie usercookie = new HttpCookie("LoginTime");
usercookie.Value = DateTime.Now.ToString();
Response.Cookies.Add(usercookie);
HttpCookie namecookie = new HttpCookie("LoginName");
namecookie.Value = obj.DisplayName;
Response.Cookies.Add(namecookie);
}
else
{
lblMsg.Text = "Invalid Username or Password.";
}
}
else
{
//lblMsg.Visible = true;
}
}
catch (Exception ex)
{
//lblMsg.Visible = true;
throw ex;
}
}
private void SetAuthenticationCookie(string role, string userid, string name)
{
string userdata = "logintype=user|role=" + role + "|email=" + txtUserName.Text.Trim() + "|name=" + name;
FormsAuthenticationTicket faTicket = new FormsAuthenticationTicket(1, userid,
DateTime.Now, DateTime.Now.AddHours(+1),
false, userdata);
HttpCookie authCookie = new HttpCookie( FormsAuthentication.FormsCookieName,//"martinfernandez#ispg.in",
FormsAuthentication.Encrypt(faTicket));
authCookie.Expires = faTicket.Expiration;
Response.Cookies.Add(authCookie);
}
//code inside global.asax.cs
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (Context.User != null && Context.User.Identity is FormsIdentity && Context.User.Identity.IsAuthenticated)
{
FormsAuthenticationTicket faTicket = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value);
string[] userdata = faTicket.UserData.Split("|".ToCharArray());
string logintype = "";
string email = "";
string uname = "";
string roleString = "";
foreach (string s in userdata)
{
string keyname = s.Split("=".ToCharArray())[0];
if (keyname == "logintype")
{
logintype = s.Split("=".ToCharArray())[1];
}
else if (keyname == "role")
{
roleString = s.Split("=".ToCharArray())[1];
}
}
string[] rolesArray = roleString.Split(";".ToCharArray());
Context.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(faTicket), rolesArray);
}
}
Just to touch on point #4 - it would be more efficient memory-wise to not store everyone's "User" object in memory, and re-create the object each HTTP request. This way you also re-verify the login details-- what if someone's account is compromised and the actual user changes their password to try and protect their account, but the "bad user" has already logged in? Under your security mechanism, the "bad user" can keep browsing away since the user data is cached and not re-verified each postback.
Here are the some general security measures that beginner and Advance Web Developer must follow.
#15 Steps To Secure Your Website
1 : Prevent Image Hotlinking (IMP)
Image hotlinking is the process of using someone else’s Image URL in our Website and using their bandwidth. In order to prevent this mystery, we can prevent access for external server by adding following line in code.
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?yourdomain.com [NC]
RewriteRule \.(jpg|jpeg|png|gif)$ - [NC,F,L]
2 : Prevent CSRF (Cross Site Request Forgery) Attacks
In order to prevent CSRF attacks on your GET and POST requests for form submission, you can use following 2 techniques.
The first it to include a random token with each request, this is a unique string that is generated for each session.
The second method is to use random name for each form field.
3 : Prevent Directory Access / Disable Indexing
Add the following line to your .htaccess file.
Options -Indexes
4 : Secure your Private and CMS Login with IP restrictions
IP restriction is a bit way advanced yet effective method to stop the unauthorized personnel to access a particular area of your website.
Here is an example htaccess code to IP restrict the access to a particular location.
ALLOW USER BY IP
<Limit GET POST>
order deny,allow
deny from all
allow from 1.2.3.4
</Limit>
5 : Protect your .htaccess file
You can write this below piece of code in your htaccess file which do not let any others access your htaccess file.
<Files ~ “^.*.([Hh][Tt][Aa])”>
order allow,deny
deny from all
satisfy all
</Files>
6 : Function access rule
By adding "_" as a prefix for Function name, we can prevent function to be called from The Web publicly. This is the best practice when we need some specific function to be accessed via AJAX only.
7 : Lock down your directory and file permissions
File permissions define who can do what to a file.
"Read" = 4 : View the file contents.
"Write" = 2 : Change the file contents.
"Execute" = 1 : Run the program file or script.
8 : Prevent Cron Job to be run from Web Browser
By adding, following line of code in your page, you can protect your page to be accessed from a web browser.
if( ! $this->input->is_cli_request() ) {
die("Only CLI Requests Allowed");
}
9 : Hide admin pages to be crawled by Google
You do not want your admin pages to be indexed by search engines, so you should use the robots_txt file to discourage search engines from listing them.
10 : Disable Right Click on Page if not require
Disabling “right-click” as a way to view your website source code by inspect element to secure Website content for general users.
11 : Use Strong Password for CMS
Keep practice to set random Password with the special character only.
12 : Make Admin Directory Tough to guess
It may happen that Hackers can use scripts that scan all the directories on your web server for giveaway names like ‘admin’ or ‘login’ etc. and your significant stuff may get leaked.
13 : Change your database table prefix
Add a prefix (the mixture of project name and year) which would be hard to presume for a secured side.
To illustrate,
A) BPM Supreme => bpm14_download
B) Glickin => gk15_admin
C) TravelWorthy => tw16_user
14 : Prevent User's Password, that's as important as yours
Regarding Password Encryption algorithm, Use sha1 algorithm instead of tradition algorithm Md5 which is the very old way and becoming less secure nowadays as per sources.
Reference : http://php.net/manual/en/function.sha1.php
15 : Hide Error Log
During development Mode, keep error reporting "ALL" and once we go LIVE change it to "0" without forgetting. Over here
Reference : http://php.net/manual/en/function.error-reporting.php
My advice would be to use asp.net membership and roles (Microsoft). It is a very good security solution - login security, roles (permissions) and is stored in a SQLServer database (not sure if it can be stored elsewhere).
I use it on my site and you can use membership controls straight out of the box (login forms, change password, etc.) or you can roll your own.
The only tricky bit I found was setting up the membership tables, views and stored procs in my dB (you download a dB script), but really it was fairly straightforward to implement.
Here's a link to asp.net membership and roles
I have a classic ASP page - written in JScript - that's using Scripting.FileSystemObject to save files to a network share - and it's not working. ("Permission denied")
The ASP page is running under IIS using Windows authentication, with impersonation enabled.
If I run the following block of code locally via CScript.exe:
var objNet = new ActiveXObject("WScript.Network");
WScript.Echo(objNet.ComputerName);
WScript.Echo(objNet.UserName);
WScript.Echo(objNet.UserDomain);
var fso = new ActiveXObject("Scripting.FileSystemObject");
var path = "\\\\myserver\\my_share\\some_path";
if (fso.FolderExists(path)) {
WScript.Echo("Yes");
} else {
WScript.Echo("No");
}
I get the (expected) output:
MY_COMPUTER
dylan.beattie
MYDOMAIN
Yes
If I run the same code as part of a .ASP page, substituting Response.Write for WScript.Echo I get this output:
MY_COMPUTER
dylan.beattie
MYDOMAIN
No
Now - my understanding is that the WScript.Network object will retrieve the current security credentials of the thread that's actually running the code. If this is correct - then why is the same user, on the same domain, getting different results from CScript.exe vs ASP? If my ASP code is running as dylan.beattie, then why can't I see the network share? And if it's not running as dylan.beattie, why does WScript.Network think it is?
Your problem is clear. In the current implementation you have only impersonation of users and no delegation. I don't want to repeat information already written by Stephen Martin. I only want to add at least three solutions. The classical way of delegation which Stephen Martin suggests is only one way. You can read some more ways here: http://msdn.microsoft.com/en-us/library/ff647404.aspx#paght000023_delegation. I see three practical ways of you solving your problem:
Convert the impersonation token of the user to a token with delegation level of impersonation or to a new primary token. You can do this with respect of DuplicateToken or DuplicateTokenEx.
Use S4U2Self (see http://msdn.microsoft.com/en-us/magazine/cc188757.aspx and http://msdn.microsoft.com/en-us/library/ms998355.aspx) to receive a new token from the old one with respect of one simple .NET statement WindowsIdentity wi = new WindowsIdentity(identity);
You can access another server with respect of one fixed account. It can be a computer account on an account of the application pool of the IIS. It can be another fixed defined account which one will only use for access to the file system.
It is important to know which version of Windows Server you have on the server where IIS is running and which Domain Function Level you have in Active Directory for your Domain (you see this in "Active Directory Domain and Trusts" tool if you select your domain and choose "Raise Domain Functional Level"). It is also interesting to know under which account the application pool of the IIS runs.
The first and the third way will always work. The third way can be bad for your environment and for the current permission in the file system. The second one is very elegant. It allows control of which servers (file server) are accessed from IIS. This way has some restrictions and it needs some work to be done in Active Directory.
Because you use classic ASP, a small scriptable software component must be created to support your implementation.
Which way do you prefer?
UPDATED based on the question from comment: Because you use classic ASP you can not use a Win32 API directly, but you can write a small COM component in VB6 or in .NET which use APIs which you need. As an example you can use code from http://support.microsoft.com/kb/248187/en. But you should do some other things inside. So I explain now which Win32 API can help you to do everything what you need with tokens and impersonation.
First of all a small explanation about impersonation. Everything works very easy. There are always one primary token under which the process runs. To any thread another token (thread token) can be assigned. To do this one needs to have a token of a user hUserToken and call API ImpersonateLoggedOnUser(hUserToken);.
To go back to the original process token (for the current thread only) you can call RevertToSelf() function. The token of user will be received and already impersonated for you by IIS, because you so configured your Web Site. To go back to the original process token you should implement calling of the function RevertToSelf() in your custom COM component. Probably, if you need to do nothing more in the ASP page, it will be enough, but I recommend you be more careful and save current users token in a variable before operation with files. Then you make all operations with file system and at the end reassign users token back to the current thread. You can assign an impersonation token to a thread with respect of SetThreadToken(NULL,hUserToken);. To give (save) current thread token (user token in your case) you can use OpenThreadToken API. It must work.
UPDATED 2: Probably the usage of RevertToSelf() function at the end of one ASP page would be already OK for you. The corresponding C# code can be so:
Create a new Project in C# of the type "Class Library" with the name LoginAdmin. Paste the following code inside
using System;
using System.Runtime.InteropServices;
namespace LoginAdmin {
[InterfaceTypeAttribute (ComInterfaceType.InterfaceIsDual)]
public interface IUserImpersonate {
[DispId(1)]
bool RevertToSelf ();
}
internal static class NativeMethods {
[DllImport ("advapi32.dll", SetLastError = true)]
internal static extern bool RevertToSelf ();
}
[ClassInterface (ClassInterfaceType.AutoDual)]
public class UserImpersonate : IUserImpersonate {
public UserImpersonate () { }
public bool RevertToSelf () {
return NativeMethods.RevertToSelf();
}
}
}
Check in project properties in "Build" part "Register for COM interop". In "Signing" part of the project check Sign the assembly and in "Choose a strong name key file" choose <New...>, then type any filename and password (or check off "protect my key..."). At the end you should modify a line from AssemblyInfo.cs in Properties part of the project:
[assembly: ComVisible (true)]
After compiling this project you get two files, LoginAdmin.dll and LoginAdmin.tlb. The DLL is already registered on the current computer. To register if on the other computer use RegAsm.exe.
To test this COM DLL on a ASP page you can do following
<%# Language="javascript" %>
<html><body>
<% var objNet = Server.CreateObject("WScript.Network");
Response.Write("Current user: ");Response.Write(objNet.UserName);Response.Write("<br/>");
Response.Write("Current user's domain: ");Response.Write(objNet.UserDomain);Response.Write("<br/>");
var objLoginAdmin = Server.CreateObject("LoginAdmin.UserImpersonate");
var isOK = objLoginAdmin.RevertToSelf();
if (isOK)
Response.Write("RevertToSelf return true<br/>");
else
Response.Write("RevertToSelf return false<br/>");
Response.Write("One more time after RevertToSelf()<br/>");
Response.Write("Current user: ");Response.Write(objNet.UserName);Response.Write("<br/>");
Response.Write("Current user's domain: ");Response.Write(objNet.UserDomain);Response.Write("<br/>");
var fso = Server.CreateObject("Scripting.FileSystemObject");
var path = "\\\\mk01\\C\\Oleg";
if (fso.FolderExists(path)) {
Response.Write("Yes");
} else {
Response.Write("No");
}%>
</body></html>
If the account used to run the IIS application pool has access to the corresponding network share, the output will be look like following
Current user: Oleg
Current user's domain: WORKGROUP
RevertToSelf return true
One more time after RevertToSelf()
Current user: DefaultAppPool
Current user's domain: WORKGROUP
Yes
Under impersonation you can only access securable resources on the local computer you cannot access anything over the network.
On Windows when you are running as an impersonated user you are running under what is called a Network token. This token has the user's credentials for local computer access but has no credentials for remote access. So when you access the network share you are actually accessing it as the Anonymous user.
When you are running a process on your desktop (like CScript.exe) then you are running under an Interactive User token. This token has full credentials for both local and remote access, so you are able to access the network share.
In order to access remote resources while impersonating a Windows user you must use Delegation rather then Impersonation. This will involve some changes to your Active directory to allow delegation for the computer and/or the users in your domain. This can be a security risk so it should be reviewed carefully.