Creating a Forms Authentication cookie for a search engine crawler - asp.net

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)....

Related

Granting Secure Access from one website to another

I'm really just looking to see how much folly is in the below suggestion from a security perspective.
I have two websites. One is an administration portal and the other is a members portal.
Within the administration portal administrators can retrieve a listing of members and I need to offer the ability for administrators to login to the member portal without having to enter the members login credentials.
Both are separate websites within IIS and for this discussion lets say they are on different servers.
Both websites access the same SQL Server database.
I was thinking that I could on the administrator clicking a "Login as Member" link create a random code string and save this to the database along with the member number.
I could then pass the code and member number to the member portal as query string parameters.
The member portal then read in these values and checks them in the database to verify that the code string exists and if so that it matches the member number also being passed. I could then login the member and set a flag in the database to set the code as being used and therefore invalid for future requests.
I'm thinking to bypass this a hacker would need to successfully guess the random code and pass that to the page alongside the corresponding member number for that code and for that combination to be marked as unused in the database.
This would seem to be unlikely given that only seconds will pass between the code being generated and the code being used.
If necessary I could always check the IP address of the request as users of the administration portal all share the same fixed IP address.
So do you think the above would stand up to scrutiny on a security review or will I need to go down the SSO route?
Your approach is very sound. I can confirm because I have implemented just such a solution for just such a reason. We analyzed the options and exposure. And after implementation, our application passed a PCI Complaince Audit.
Reasons:
SSL is Esential! protects against sniffers. Essential. Without Encryption, sniffers could detect your GUID and may have a window to use it)
As Tony pointed out, the GUID is effectively unguessable.
Guid Tokens expiring should expire within 24 hours.
Suggestions:
Checking against IP is good. But don't be fooled into a feeling of security from it. Anyone can fake IP's in headers. To be Secure against XSS and CSRF by using AntiForgery tokens.
The AntiForgery token is a cookie that populates your HTTPHeaders with __RequestVerificationToken which is almost as hard to guess as your GUID.
Consider using an established Authentication framework like .NET Identity 2 and multitenancy.
An established framework takes the burden of encrypting your passwords. MS Frameworks like Simple Membership and Identity integrate into modern ASP.NET frameworks and give you very strong base of functionality to lean on.
If you're using an old framework like classic ASP or .NET 2.0, the classic Membership Provider is more appropriate.
If you are creating new MVC 5 applications utilizing Entity Framework, I strongly suggest using Identity 2.1.
Consider Mult-Tenancy. While there is nothing wrong with your solution, if Admins and users shared Membership Provider, your solution would be cleaner. An admin could log into the main site and "get" the token from the DB. Then no exposure.
Assuming the use of HTTPS and adequate physical and IT security processes and procedures in place for the administrators, this method should be adequate. It is more secure than most financial website password resets, which typically only require a compromised email account and some personal information to reset the password. If you check the IP address range of the originating client request as well, a hacker would have had to already have access to your systems or network. Also, if you make the code a GUID, it would be (pragmatically speaking) impossible for someone to guess.
You could add a layer of checking for hack attempts by storing a record in the database each time this event occurs (or at least each it fails due to a bad key), and each time it occurs run a check to see if it is happening too often (like 100 times in the past hour, or something--the right number depends on how often you expect it to happen). If it's happening too often, then have it send an alert to IT personnel and revert so that the user has to enter their credentials manually.
Disclaimer: I am not a security expert by any means, so I'll gladly defer to anyone claiming such status. I'm weighing in here due to a lack of answers.

Multiple site domains and virtual directory single login

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.

Secure a single page in an ASP.NET app

I often have a need to secure a single page (i.e. Reports) on a public facing app so that only authorized users may access the page. In the past, this mean setting up a custom login form or using the ASP.NET membership provider or something else far too complex to serve the purpose. Is there an easier (safe) way to secure a single page in this fashion?
Some things I've considered:
Client certificates (initial setup is a pain)
A single master password (works in a pinch, but feels dirty)
Restrict access by host address (cumbersome when the need arises to allow external users access to the page). Also, need to support access via proxy (X-Forwarded-For) which can be faked by technical users)
Are there other options? Recommendations?
You can do it in your web.config file something like what is suggested here. As far as authentication is concerned the easiest way is to use windows authentication.
A login system is your best option. If you don't want to go through the trouble of setting up and managing a login system yourself, consider using OpenAuth.
You can achieve functionality pretty easily using DotNetOpenAuth. Users can then log in with their Google, Yahoo, StackOverflow, etc. accounts, and you get a token that you can store to limit access with.

ASP.Net Authentication and Authorization options

I have the usual requirement of implementing Authentication and Authorization. I used to implement it using custom code where I have Users, Roles, Role_Pages, User_Pages, and User_Roles. So this way we can give a certain user roles (that group multiple pages) and/or directly define access to certain pages. All that with the ability to specify fine grained permissions like the ability to Add/Edit/Delete records in those pages.
My question: How easy is it to implement this using Forms Authentication and what advantage does that give over implementing a custom solution. I am also concerned with knowing if there would be any advantage when it comes to securing from session hijacking and against spoofing where an attacker could replay requests and impersonate legit users. Would Forms Authentication have any advantage there, or is it only SSL that can secure against that (which makes both approaches equal in that regard).
Forms authentication is just a mechanism for passing an authentication token from the browser to the server, which serves as the requestor's identity. I take it right now you're using a Session variable to remember the logged in user's information? That is akin to forms authentication because Session state is maintained (in part) through a cookie. Similarly, forms authentication creates a tamper-proof identity token and stores it using a cookie so that when the user makes subsequent requests, the cookie is sent to the server, which says, "Hey, I'm user X." Forms authentication, as it's name says, is just a mechanism for authenticating - that is, identifying - visitors.
For authorization you would typically use URL authorization, which is a mechanism through which you specify in Web.config, These are pages that are (or are not) accessible to certain users (and/or roles). Again, though, URL authorization, as its name implies, is just a mechanism for authorizing users, for determining if a given requestor has the rights to retrieve a certain resource.
So how do you store user information, like username, email, password, and so forth? That's where Membership comes into play. It's an extensible framework for creating and storing and managing user accounts. There's also the Roles system, which is a similarly extensible model for creating roles and associating them with users.
These, then, are the tools and frameworks you should explore: forms authentication, URL authorization, Membership, and Roles. They are complementary technologies and are (usually) used in tandem.
To address you specific questions:
How easy is it to implement this using Forms Authentication and what advantage does that give over implementing a custom solution.
Forms authentication (and URL auth and Membership and Roles) are pretty easy to implement. There are three primary advantages to using these technologies rather than a custom solution:
Using these technologies is more efficient. You don't have to reinvent the wheel, thereby saving you oodles of time.
Using these technologies leads to less buggy code. If you implement a custom solution you may have a security hole or bug that you don't catch during testing. Forms auth and URL authorization have both been around since ASP.NET's inception (nearly a decade now) and have been used and "tested in the field" by millions of developers around the world. Membership and Roles have been around for 5-6 years with similar levels of field testing. Obviously, you can't say the same about your custom solution.
Using these technologies makes your application more maintainable. If you need to hire a new dev to help on the site, chances are she'll already be familiar with forms auth et al, but would need to spend time to come up to speed with your custom solution.
I am also concerned with knowing if there would be any advantage when it comes to securing from session hijacking and against spoofing where an attacker could replay requests and impersonate legit users. Would Forms Authentication have any advantage there, or is it only SSL that can secure against that (which makes both approaches equal in that regard).
Forms auth has very tight security (presuming you're using the default settings). The authentication ticket is encrypted and digitally signed and has a time-based expiry built in (to reduce the surface area for replay attacks). I'm not sure your what your current, custom solution uses for identity since you didn't mention it, but I'd wager it's session state. That will be just as "secure." The point is, the identity tokens - the session cookie in your case and the authentication ticket in the case of forms auth - are both secure and can be safely transmitted over the Internet without SSL.
Regardless of what approach you use, however, it is imperative that you SSL protect, at minimum, the sign in page. This is the page where a user enters his credentials. If that page is not being accessed over SSL then the user's credentials will be sent over the Internet in plain text.
would [Membership, Roles, etc.] give me the ability to assign users access to certain pages directly and at the same time through Roles (that group access definition to multiple pages)
URL authorization allows you to lock down an entire page based on the user/role. To grant access to particular features on the page you would have to write your own code/logic.
To learn these technologies, I will, shamelessly, recommend that you check out my tutorials on website security. There are a total of 15 step-by-step tutorials in both C# and VB with complete, tested, working demo code you can download. They cover the gamut of user account-related scenarios, from forms auth to URL authorization to role-based authorization to creating and managing user accounts.
Here is the URL again: http://www.asp.net/security/tutorials
Happy Programming!
Maybe you should look at asp.net membership provider:
http://msdn.microsoft.com/en-us/library/yh26yfzy.aspx
Everything is there and highly customizable

ASP.NET Application to authenticate to Active Directory or SQL via Windows Authentication or Forms Authentication

I am in the process of writing an application that will need multiple forms of authentication.
The application will need to support authentication to Active Directory, but be able to fail back to a SQL Membership Provider if the user is not in Active Directory. We can handle the failing to the SQL Provider in code based on the username provided because the username will be a different format than the Active Directory username.
Is this even possible? What I mean is, can I use membership and use both ActiveDirectoryMembershipProvider and SqlMembershipProvider together or will I have to roll my own?
Another additional added complexity is that I would like to automatically authenticate my internal users based of Windows Authentication back to AD, but use Forms Authentication for users not on our internal network, or users that are using the SQL Provider.
These will most likely be separate servers, one internal, and the other external so I have a lot of planning to do to figure out the data replication, and how I will authenticate the AD users if they hit the outside server etc.
I am wondering what thoughts are out there as I start down this road. Is what I am wanting to do even possible without me rolling my own, or is there a way to mesh these together?
Thanks for the reply.
The reason I asked originally was because I was able to get this specific senerio working about 7 years ago using IIS to authenticate and then passing back the credentials to a Lotus Domino Server Web App. If the user was not authenticated via the Windows Authentication/ISS then Domino would handle the authentication. This was what I was looking to do here, but really couldn't think of a way to make it work in IIS.
As for the rest of your reply, I think you are on to the way that I will need to take. I have thought this through and tossed it around in my head a lot. The application will be somewhat different on the two servers anyway since there is going to be limited access to the data on the external server anyway. The fact that so much is going to be different already I may just treat these as two applications, thus negating the need to use two types of authentication in the same application anyway.
I am playing around with the idea already of writing my own authentication/login window for the external server, and if the user trys to log in with their AD credentials on the external server I will be able to detect that and redirect them to the internal server. If they are not on the local network or VPN'd in they will simply not get access. This part still has some thought process to go though so I am not sure.
As an additional thought - is there a way to pull just enough of AD into a SQL database to allow me to authenticate users to the SQL database from the external server using their AD credentials, without creating any security issues? I hope I am clearly typing what I am thinking....
Thanks again!
Tim
This is the way I've handled a similar situation based on this info:
Configured the application to use Forms authentication.
Set the LoginUrl to a page called WinLogin.aspx.
In WinLogin.aspx, use Request.ServerVariables["LOGON_USER"] to get the username then call FormsAuthentication.RedirectFromLoginPage( authorizedUserName, false ) to log them in. I guess you can manually check Active Directory as this point as well.
Create an html page that redirects to a page called Login.aspx
Login.aspx is your standard username/password login.
In IIS, Enable Integrated Authentication and Anonymous on the entire site, but deny anonymous access to WinLogin.aspx.
In IIS, set your 401 errors to the page created in step 3.
What basically happens is that when an unauthenicated user hits the site, they're redirected to WinLogin.aspx. Since anonymous is turned off, integrated security makes a check. If that passes, your custom code in WinLogin can run. If the integrated security check fails, a 401 error occurs. Your custom 401 page redirects to Login.aspx where the user can log in using their username and password with the SQL provider.
As far as I know, Web Applications are configured to use either Windows Authentication or Forms Authentication, but not both. Therefore, I do not believe it is possible to automatically authenticate internal users while requiring others to enter a username / password.
You could authenticate to Active Directory or a SQL user store via Forms authentication by using a custom provider. However, the AD users would still need to enter their username and password. Although I've never combined these two methods, I have used Forms authentication to authenticate against both sources at one time or another.
With that said, I think you may want to consider reducing the "flexibility" of your system. If you have an external facing server and an internal facing server, you could simply change the provider configuration on each copy of the application to go against a different source. Then, you could configure the internal one to use Windows (automatic) authentication and the external one to use Forms authentication.
IMHO, I believe that internal users should not be using the external server to access the application. If they are, they should have a user account stored in SQL, completely separated from their AD account. Basically, when someone accesses the application externally, they are acting as an external user, irregardless of their physical location.
Well, it is possible to use ActiveDirectoryMembershipProvider and SqlMembershipProvider, but this requires you design your log on page with your own code instead of the Login controls.
About the mix authentication (Windows and Forms), as far as I know only IIS 7 makes it easy and clean. See this post for details,
http://mvolo.com/blogs/serverside/archive/2008/02/11/IIS-7.0-Two_2D00_Level-Authentication-with-Forms-Authentication-and-Windows-Authentication.aspx

Resources