So here's the scenario i'm trying to find a solution for.
my company currently has a records system for it's staff, but it is not linked to active directory. we have duplicate, and often inaccurate data because of this. what i'm trying to do allow the records system to update values in active directory, however i want to scope what can be changed and by who. so
when we have a new hire, IT will enter in the initial record, which would also create the AD user.
hr comes along and updates title/description/phone/address etc., but they shouldn't be able to create or delete a record from the system. (they'll have to file a ticket, or something)
i've been trying to read about the kerberos double-hop problem, and it seems i need the ability to delegate, however, my own IT powers aren't high enough. i could escalate and try and get sign off from the higher level IT folks to grant delegation to an account, but i'm saving that as a last resort.
I would like to accomplish things using impersonation, but i'm having a hard time finding a clear answer on how to implement impersonation.
i have enabled impersonation in web.config, and in iis. i have set the appPool Identity to network service. after that, i'm lost on what to do next or how to test settings.
edit 1:
i'm also following this pattern for impersonation
var iid = HttpContext.Current.User.Identity;
WindowsIdentity wi = (WindowsIdentity)iid;
WindowsImpersonationContext wic = wi.Impersonate();
try
{
// do something with a directory entry here
}
catch
{}
finally
{
wic.Undo();
}
Make sure your web server has delegation enabled in AD. That's the step I always forget about anyway.
Couple reference links:
http://blog.reveille.org.uk/2010/01/asp-net-impersonation-delegation/
http://support.microsoft.com/kb/810572?wa=wsignin1.0
Also make sure you're using windows auth for the website.
You'll be able to tell real quick if its working as only users with proper AD access will be able to manipulate the AD settings (because it will literally be just like they're making the AD change themselves).
Delegation is a stronger form of impersonation. Impersonation lets you act as the user on the local computer, delegation allows you to act as the user on remote computers. The only way to avoid delegation is to delegate control in AD to the web service (in this case you're running as the network service, so give the web server's computer account the ability to write to the desired attributes), and have the web service perform the updates. This is not a good idea though, since you can't attribute the changes to the user who was using the website.
Related
A client requested that we develop a site for them but instead of the standard ASP.NET authentication or using Active Directory accounts, they would like us to use SQL server accounts for authentication. (That is, an account using SQL Server authentication.)
This website would be exposed to the public Internet and would have users that are not employed by the client and the client's Active Directory is not available in their DMZ.
So I have a few questions on this:
1) Is this a good idea? (Our gut feeling is that it's not.)
2) How should we best go about doing this?
Off the top of my head, the best answer I can come up with for how to do this would be to dynamically build a connection string based off the credentials the user enters in a web form. If the connection is successful, continue to the site. Otherwise, kick them back out to the login page. (And, of course, make sure accounts get logged out in the event of too many failed logins.)
Is there a better way?
Thanks.
1) Is this a good idea? (Our gut feeling is that it's not.)
There are a few problems using this. Notably, you would have to run your application as an escalated user to perform user maintenance-- add/inactivate users, change passwords, etc... Running a web-app with escalated permissions on the database is generally frowned on. If you run this kind of thing outside of your application, then you'll need to get your DBA to run all the user maintenance stuff, which isn't fun. Also, if you have requirements around password complexity, password rotation, etc., you may find SQL Server authentication lacking over what would be available in AD, for example.
2) How should we best go about doing this?
You can easily test credentials provided by attempting to login to SQL Server using the supplied credentials. You can read the connection string from your configuration settings, but then load it into a SqlConnectionStringBuilder object (in System.Data.SqlClientsomewhere), manipulate it to use the supplied credentials, and then connect using the result of that manipulation to test if the credentials were valid.
You would want to use that only for testing your login. After that, you could go back to using your normal connection strings.
I am creating a project which has a login portal with multiple applications and websites. I want to allow the user to login and then click any application and have access to it. Some considerations are: each application is defined in a user profile, ie which users can see what. also each application privileges are different for each user. so user a may be an administrator of application a but just a normal users in application b.
What i know.
I can have one auth cookie created in the main portal which with setting the machine key and same authcookie name, each application can use it. I have done a test with this and it seems to work.
My problem
As each site/ virtual directory has different privileges per user and per application when the user access a site i need to get his privileges from the databases but I cant then overwrite the auth cookie userdata with the new details because he may have multiple tabs etc open at a time on different sites. So how can i have an extra cookie store per user and per application for holding application specific details. I know I could go to the database each time but that's allot of overhead for each post back.
Maybe another option is to use the main authcooke for checking the user is logged in then have a new auth cookie per aplication and user, but how can i have 2 authcookies, that may get confusing and the second needs to timeout when the main one does et c i think
Any help suggestions would be gratefully appreciated
THanks
------------------- EDIT -----------------------------
we have one user table for all all sites not 1 per each site. then we map the user to an application and then the user application and role. so when you get to an application it has to check if the user has access and what there role is. all other user details are already in the auth cookie when loggedinto the main site. We do it this way because we have to manage users in one application not each application. Hope this helps understand my requirements.
What you are describing is a 'classic' SSO (single sign-on) example. There are lots of ways people have tried this and they are well documented on Google.
One way to do this is to have your SSO server (e.g. the first place you land and log in) to issue a security 'token' (e.g. a Guid) and then either store this in a cookie or append to URLs. Each subsequent call to an application can look-up the token in a database, verify it's validity and carry on (or boot the user out if invalid).
Using a database also allows you to set a timeout for all applications for which the token is valid.
This can then be extended to allow the database to store which apps each user can access etc. I've described this in very broad terms but it may be a good starting point.
Hope this helps
BTW: querying the database on each request isn't too much of an overhead. I have applications that do just that and are still performant when loaded with 300+ users.
The following webpage talks about using impersonation in code (ASP.NET): http://support.microsoft.com/kb/306158. I am thinking about creating a class for the code, then the application can call impersonateValidUser and undoimpersonation.
I am concerned about putting usernames and passwords in my code as surely anyone will be able to see them using a tool like ILDASM. What is the best way to hide these passwords?
The article has a section titled: Impersonate the IIS Authenticated Account or User. I thought about creating an impersonated user in the Web.Config, but this would mean that the entire application is run as the inpersonated user. I only want a very small part of the application to run as the impersonated user - when it is necesary to access and update active directory.
I really like your intention to have have only the part of the application that does the AD updates running under a highly privileged account. I also share your concerns about storing the password in the web.config or in the code.
I can think of two options for you.
Store the account details in the web.config and encrypt that part of the web.config. That will ensure that only an administrator of the web server can get hold of the password. Someone else getting hold of the web.config won't understand a thing of the password.
Create a small, separate WCF service with the AD update code. Then run that WCF service in a separate application pool, with the app pool set to the identity of the user that has access to the active directory. Setup a restricted, localhost-only endpoint for the WCF. The WCF service should have access control to only allow access from a dedicated account. That account should be set as the identity of the app pool of the main web site.
Option 1 is easier to implement and protects the password rather well. Option 2 offers better protection for the passwords as they are not stored in the web.config at all - they are part of the IIS configuration. Option 2 also adds complete isolation between the privileged code and the rest of the system as it runs the AD update code in a separate process. With that isolation, it is much easier to make a code review for the AD code to check for security issues.
I am quite confused about this and none of the texts / docs / SO questions have elucidated the matter for me.
I want my asp.net MVC app to be able to save an XML doc to a folder on the server. But I am getting an exception...
Access to the path 'D:\blah\blah\folder\xml_data.xml' is denied.
So as I understand it my application is running under a user account that does not have write permissions.
I think I had this problem before and my solution was to contact my web host and ask them to give my site permissions.
But what if I want to create my own custom set of roles with corressponding permissions? Do these have to be added into IIS? Would I have to create a list and then hand it over the the web host? What would such a list look like? As I understand it, it is not possible to configure roles and permissions in web.config, is that correct?
Once I have the roles and their permissions set up how to I set the default role for the app to run under and also how do I programitically change the role that the app is running under?
ps. I don't want to use asp.net membership I would like to know how to set this up myself.
Use asp.net membership. I don't care if you don't like it. Use it. It's easy, it's simple, and it gets security right. You will mess security up if you do it yourself and don't know what you're doing.
People give membership a bad rap, it's a good tool. Most people just make the wrong assumptions about it.
You define your roles in the membership/role API. This is stored in your database. You can't have roles without a user to apply them to, so you need a membership system of some type.
EDIT:
There are two kinds of users here. The first is the user that the ASP.NET worker process runs as under IIS. This is the user that your host must define, and allow to access various folders to access files.
The second is the IIdentity user of asp.net, this is the user that asp.net defines for the logged in web user, and this is completely seperate from the Worker process user. IIdentity users have no inherent operating system rights or privileges, other than those assigned to the worker process identity.
In other words, IIDentity based users run as the same Worker process identity in IIS.
The exception to this is when you define "impersonate=true" in the web.config, and this allows the worker process to "log on" to the OS as the user in question. In other words, the worker process will run as the web users credentials. This requires that the web user have credentials in the OS as well.
The other exception is that you can specify a specific OS user to impersonate in the web.config. But, again, there must be an operating system user to impersonate. Also, impersonation is a very expensive operation and takes a lot of system resources.
See http://msdn.microsoft.com/en-us/library/aa292118(v=vs.71).aspx
Big picture: I have been asked to create a search engine for our company's intranet. Such a search engine will crawl pages supplied to it by XML files for each independent application on the intranet. Problem is, the entire intranet is using Forms Authentication, and so the crawler will have to have access to each application without actually having user credentials (e.g. username and password).
Each application within the intranet has its access controlled by a permission manager, which is essentially a wrapper on the default Role Manager ASP.NET comes with. Each application can define its own roles and assign people who have those roles.
Please note that there are potentially hundreds of applications.
The crawler has access to the permission manager's database, so it knows what all the roles are. Therefore my idea was to have the crawler create a cookie that identifies it as having all roles for each application.
The problem I'm running into is this: how do I create a forms authentication cookie which already has the roles assigned in it without creating a corresponding user (IPrincipal).
It is entirely possible that I've failed to completely understand how Forms Authentication works, and if so, please tell me what I can do differently.
This is probably not what you want to hear, but...
I would just have the crawler authenticate like anyone else.
Given that this is a crawler you control, why fight Forms Authentication? Seems logical to create a user with all required roles in each application (hopefully you have a central administration point for the hundreds of apps, else I would not want to be an administrator there ;-)
If you do anything that allows "just the crawler" special access (bypass user-based authentication based on... what? The crawler's user agent? A specific origin IP?), you create a security hole that a hacker can leverage to gain access to all of the intranet applications that have otherwise been diligently secured with user IDs, passwords and roles (in fact, the security hole is particularly wide because you propose granting access to EVERY role in the system).
It sounds like what you want is an appropriately encrypted System.Web.Security.FormsAuthenticationTicket (which then gets attached to HTTP requests as a cookie).
The encryption logic is located in System.Web.Security.FormsAuthentication.Encrypt(), which I think uses the MachineKey as the encryption key. Also have a look at the GetAuthCookie() logic (using Reflector).
You might have to write your own version of the encryption method, but what you want to do should be possible, provided you have a copy of the remote site's encryption keys. You don't need the user's passwords -- only the user name is encoded into the Ticket.
It seems to me that the problem is not yet well defined, (at least to me!).
Why do you need to crawl the pages and index them if there are fine grained permissions on them?! How do you show search results without violating the permissions? Why not index the back end by passing the pages altogether (I mean index the database records not the pages)....