I have a website that is using Windows authentication that calls an API. The API has the Authorize attribute:
[Authorize(Roles = #"myrole.local\role")]
The API then makes a call to a method in my business layer that does this:
string [] directories = Directory.GetDirectories("\\\\server\\folder\\folder2");
When running locally this works as intended. When my IT ops guy checks the audit logs, he sees that my login has accessed that folder.
Now when I deploy my website to our development environment, it no longer works (we get an "access denied" error for that folder). So we looked into it and found that the user trying to access the folder was our server (something like server$) tried to access folder and failed.
So my question is: how do I access the folder with the current user that is logged in? I have looked this up here on Stack Overflow and I see impersonation comes up a lot. I have tried this example with no luck:
public static List<DirectoryName> GetDirectories(IPrincipal user)
{
string[] directories;
using (WindowsImpersonationContext impersonationContext = ((WindowsIdentity)user.Identity).Impersonate())
{
//Insert your code that runs under the security context of the authenticating user here.
directories = Directory.GetDirectories("\\\\server\\folder\\");
}
}
I am still denied access.
I have the user that is logged in though, so I know I can 'see' them, but the folder I am trying to access says it's the server.
Does anyone know how to get around this? Am I missing something?
P.S. I have created the website with IIS and have set both the API and website to use windows authentication. (anon = false;); but still it says the server is trying to access the folder.
P.P.S. In the web.config for the API, I have these tags as well:
<system.web>
<!-- ... -->
<authentication mode="Windows"/>
<authorization>
<allow roles="group.local\group" />
</authorization>
</system.web>
Edit: So we were able to access the folder path with the logged in user but only when going to the website on the server.
If we go to the website off our dev server we will then get an access denied error. Also there is no audit line when this fails.
Hopefully this edit provides more insight.
Related
I have searched through web and tried all possible solution but my web app failed every time !
I have bunch of shared drive paths which I want to access through Web app. I have credentials to access this shared drive paths.
The possible solution I found was enable identity impersonate but my web app is failing me in that case. I tried accessing it Using UNC API but that is failing too. I have been told that I can access this shared drives as directory service (dont need to use UNC API).
Share your thoughts if you have any !
Thank you!
Enable Identity Impersonate
In Web.Config
<identity impersonate="true" userName="username" password="pass">
and it is not able to locate my project when I am enabling identity impersonate
--Gives System.IO.DirectoryNotFoundException
(tried changing authentication mode(Windows,None,etc) in web.config -- same above error)
UNC Access
I took a copy of UNCAccessWithCredentials from here
https://www.codeproject.com/Articles/43091/Connect-to-a-UNC-Path-with-Credentials
using (UNCAccessWithCredentials unc = new UNCAccessWithCredentials())
//access network drives through functional id
{
try
{
if (unc.NetUseWithCredentials(sharedrive, functionalID, domainName,
functionalPass))
{
string[] files = Directory.GetFiles(sharedrive);
}
}
}
It throws error 87 inside NetUseWithCredentials() method
I have been working on a project where I have a simple web page integrated with AD FS. The authentication and website are working as expected. I am using VS 2015. My goal is to limit what users can access at the site, "roles" from what I have read and researched. If the logged on user is an admin, grant full access, but if logged on as a regular user limit what pages are available.
Here is the scenario, go to my project URL which is redirected to AD FS sign on, after successful sign on you are at my website. Not much to it.
I have read so much online about different ways to achieve my goal that I am unsure which course is best or simplest to configure. What are my best options here? Keep in mind I have never developed in asp or any other code for that matter. Any help would be appreciated.
There is policy based authorization that is probably the current best practice, however it sounds like role based authorization may be sufficient for you.
To perform role based authorization you'll first need to setup a claim rule in your ADFS for the Relying Party Trust of your application that sends the Role claim type "http://schemas.microsoft.com/ws/2008/06/identity/claims/role". The claim rule would look like this,
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
=> add(store = "Active Directory", types = ("http://schemas.microsoft.com/ws/2008/06/identity/claims/role"), query = ";tokenGroups;{0}", param = c.Value);
Then when your roles arrive at your application in these claims, you'll process them with Windows Identity Foundation (WIF), which is integrated into .NET Framework 4.5+. I believe referencing System.Security.Claims is sufficient to get WIF in your project for processing roles. This "processing" however is done for you by WIF.
At this point you should be able to simply decorate controllers and methods like the following to perform role based authorization, with these Roles equating to the names of groups you are a member of in Active Directory.
[Authorize(Roles = "Administrators")]
public class AdminController : Controller
{
}
Just for interest, there are other ways to do this.
Once you have the roles, you can use IsInRole(role).
You can also use the web.config e.g.
<location path="Page.aspx">
<system.web>
<authorization>
<allow roles="Admin, OtherAdmin" />
<deny users="*" />
</authorization>
</system.web>
So here's what I'm attempting to do:
I want to secure a particular virtual directory on an ASP.NET application using Windows Authentication. The virtual directory only has one file, default.aspx. In the code-behind, I simply want to get the Windows username of the user who logged in but no matter what property I use, it returns the security context of the application.
I need the site itself to run under the context of the "AppContext" user for file permissions, etc. However, to determine whether the user is authorized to access the site, I need to use that user's Windows domain credentials.
IIdentity windowsIdentity = WindowsIdentity.GetCurrent();
logger.Info("Windows username: " + windowsIdentity.Name);
logger.Info("System.Environment.Username: " + System.Environment.UserName);
logger.Info("HttpContext: " + HttpContext.Current.User.Identity.Name);
The output is:
Windows username: DOMAIN\AppContext
System.Environment.Username: AppContext
HttpContext:
Assuming I'm logging in as myself and my Windows username is "Scott", I'd expect HttpContext to return "DOMAIN\Scott", but it returns nothing. I do get the Windows authentication dialog when attempting to access the virtual directory and I can successfully authenticate as "Scott". In the IIS7 Authentication dialog, all authentication mechanisms are turned off except for "Windows Authentication".
The strange thing is that I have another site where it's working just fine and I can't figure out what the difference is. The only difference I can see is that the working site is an actual IIS website and the one I'm currently working on is a virtual directory.
The output fom the working site is below. This is what I'm trying to replicate on the virtual directory but I must be missing something.
Windows username: DOMAIN\Scott
System.Environment.Username: AppContext
HttpContext: DOMAIN\Scott
ADDITIONAL NOTES:
Neither site has an <identity> element in web.config.
<authentication mode="Windows" /> is set properly.
Both the virtual directory and the site have only Windows Authentication enabled in IIS.
The code is being executed in the Page_Init method.
The bottom line is, I simply need to let the site itself run under the security context of the "AppContext" user (which the AppPool is configured to run as) but I need to get the currently logged in user's name in the default.aspx.cs code behind.
You'll find it in System.Threading.Thread.CurrentPrincipal.Identity.Name.
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(System.Threading.Thread.CurrentPrincipal.Identity.Name);
}
}
Add a Web.config inside folder and set <authentication mode="Windows"/>
Check your authorization settings.
If the resource is accessible by anonymous user - and no resource earlier in the request chain of the browser triggered an authentication - IIS will not authenticate the user.
So, you must have Windows authentication, and deny anonymous access, to see a user name in HttpContext.
I've got 2 MVC3 Internet websites. One (Site1) uses Windows authentication and is in the Local Intranet Zone. The second (Site2) is publicly available and uses Forms Authentication. Both sites are in the same Domain, but have a different sub-domain. I want to share authentication cookies between the two. In order to do this, they need identical settings in the web config. Sometimes this works, most of the time it doesn't. If anyone hits Site1 from outside our network, they get a 403 error, which is good. If a network user hits Site1, they're allowed in based on their network credentials. I then check their user's roles with the code below.
var userName = string.Empty;
var winId = (WindowsIdentity)HttpContext.User.Identity;
var winPrincipal = new WindowsPrincipal(winId);
if(winPrincipal.IsInRole("SiteAdmin")) {
FormsAuthentication.SetAuthCookie("siteadmin", false);
userName = "siteadmin"; //This is a Forms Auth user
}
else if(///I check for other roles here and assign like above)
Once I've checked the roles, I forward them onto Site2, creating a cookie for them if the user is in one of the roles determined in the if...statement above.
if(!string.IsNullOrEmpty(userName)) {
//Add a cookie that Site2 will use for Authentication
var cookie = FormsAuthentication.GetAuthCookie(userName, false);
cookie.Domain = FormsAuthentication.CookieDomain; //This may need to be changed to actually set the Domain to the Domain of the TVAP site.
HttpContext.Response.Cookies.Add(cookie);
}
//Network users not found in roles will simply be forwarded without a cookie and have to login
HttpContext.Response.RedirectPermanent(tvapUrl);
I've set up in the web.config a matching MachineKey (validationkey, decryptionkey and validation) for each site.
They also both have the same authentiation settings, with the exception of the mode. So my config for this looks like this.
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" name=".ASPXFORMSAUTH" protection="All" path="/" domain="mydomain.com" enableCrossAppRedirects="true" timeout="2880" />
</authentication>
I think my problem is that the 'authentication' mode is different for each one, so Site2 won't use the authentication cookie from site1. This is just a guess though. Is there anyway I can figure out the issue?
According to this article, what I have going here should work. And there have been times where I think it's worked, but it's hard to tell, as I may have cookies cached and their getting reused. I'm hoping someone can see something I'm missing here, or has an alternative solution.
UPDATE
I checked my authentication cookie on Site2 after logging in normally and found the Domain wasn't set, so I've removed that line of code.
Also, I read about cookies expiring when the date isn't set, so I set an Expire Date on my cookie before sending with the request.
So, with those two changes, here's where I'm at.
It works on Chrome and Firefox, but not with IE. Not sure. I'm going to do some additional testing from another machine and another user so I know I haven't got any residual cookies sitting around.
I determined my problem was not setting the Expires property of my cookie. According this Microsoft article, cookies won't be written to the client unless the Expires property is set.
"If you do not set the cookie's expiration, the cookie is created but it is not stored on the user's hard disk. Instead, the cookie is maintained as part of the user's session information. When the user closes the browser, the cookie is discarded. A non-persistent cookie like this is useful for information that needs to be stored for only a short time or that for security reasons should not be written to disk on the client computer. For example, non-persistent cookies are useful if the user is working on a public computer, where you do not want to write the cookie to disk."
In this case, I needed the cookie to be written to disk since I was doing a server transfer to another site, thereby ending the session for that user. I'm not 100% sure that this was the fix, but it is working now, so I'm assuming that.
I am developing a website in which I'm using forms authentication.
We have 2 log in pages: one for user, another for admin.
I added this code into webconfig file for user.
<forms loginUrl="Login.aspx" defaultUrl="Home.aspx" >
I am using this code for user side when user successfully logged in.
FormsAuthentication.RedirectFromLoginPage (UserName.Text, chkPersistCookie.Checked)
I am not using the default user membership database. I have my own database in SQL Server 2005.
I want same thing for admin, but the default url is Admin.aspx & login url is adminlogin.aspx for admin.
How can i assign in web config file for admin? Is it the right way to do that or any one have some better concept for that?
I used This line of code and this worked for me.
FormsAuthentication.SetAuthCookie(txtUser.Text, true);
Response.Redirect("Admin.aspx");
Putting admin files to a folder and creating a web.config file in it, is an option. You can probably override the config rules there.