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
Related
Everything I've read about claims-based authentication is essentially about "outsourcing" your authentication process to a trusted 3rd party.
See:
Explain "claims-based authentication" to a 5-year-old
Why Claim based authentication instead of role based authentication
Obviously this lends itself well to using something like Facebook or Google to authenticate. But what if there is no 3rd party? What if you just need users to authenticate against an internal database? For example, in a corporate setting. Is there any reason to use claims over plain old roles? If so, some concrete examples would be helpful.
What I know about claims so far:
I understand that claims are key/value pairs rather than booleans like roles.
I understand that claims can store roles.
And if I understand correctly, claims get stored in an authentication cookie (maybe this is key - fewer database calls vs. roles?).
There are numerous reasons, including these you mentioned.
Another reason is that forms authentication module is incapable of handling too large cookies. Just add few hundred roles and exceed the maximum allowed cookie size (4kb) and you are out of luck. The session authentication module that handles claim cookies automatically splits too large tokens into multiple cookies. And if you don't want to have multiple cookies, just a simple switch to "session mode" automatically stores the large token in the session container and the cookie only contains a small bit of information to reflect that.
Yet another argument for the claim-driven cookie is that you can handle any custom data, including tenant name (in a multitenant application), name of home organisation, age, whatever you can need somewhere later. Forms cookie has the custom data section but it is just a string so that you need a custom serializer to have structured data here.
All this is done by the session authentication module and, frankly, it outperforms the forms module easily then. Switching your forms authentication to the new module is also easy, I've blogged on that some time ago (other people blog about it also):
http://www.wiktorzychla.com/2012/09/forms-authentication-revisited.html
I know ASP.NET supports various authentication models like, Windows, Forms, passports and recently Claims.
I have an asp.net that prompts user to enter user name/password to login, it then compares the input username/password with the entries inside the user table of the application's Database. So, my question is, what is the term/name for this kind of authentication model? Where does this fall in the above mentioned ASP.NET supported authentication model?
I also see that many of the internet sites that I know uses this same approach.
(note: I'ev kept my App simple, of course it has user registeration/add page, profile table to authorize users, etc)
Windows, Forms, Passport, Claims, etc.. authentication are BROWSER authentication schemes. They are the mechanism the browser communicates with the server to present credentials. They have nothing to do with databases or any other storage mechanism (well, mostly..). Those are just implementation details.
FormsAuthentication uses a cookie to store an encrypted value that tells the server that the user has been authenticated. How the user is authenticated, be it by comparing things to databases, using a service, etc.. is all irrelevant if the end result is that a FormsAuthentication cookie is issued.
WindowsAuthentication is a little different in that the browser and the web server communicate to share a Kerberos ticket to verify identity, or the user enters the username password into a box that the server requests the browser to pop up. In this mode, the server itself manages the way that authentication occurs and the app isn't involved.
BasicAuthentication uses an HTTP Header to send the password in cleartext, well, technically it's an encoded password, but it's well known so anyone can unencode it. Again, the actual method that it stores the data is up to the server, and the server does this without an applications knowledge. The important part is that it's accomplished via an HTTP Header.
The same is true of other types of authentication, which are all just variations on the cookie and/or header mechanisms.
The point here is that Authentication is about how any given HTTP request identifies who the user is to the server, and ultimately the application. Not how the data is stored, or validated. So, since you did not tell us how the server and browser communicate, we can't tell you how your authentication is defined, although almost certainly it is a variation of FormsAuthentication.
EDIT:
Just a little history lesson. The reason it's called FormsAuthentication is because the authentication system does not use a pop up dialog box from the browser to enter credentials, but typically the web page provides an HTML Form for the user to enter credentials. The browser is not really involved in the authentication process at all, other than for passing a cookie as requested.
It should be more accurately called "CookieBasedAuthentication", but the name has stuck and will probably stay what it is. ASP.NET provides a specific implementation called FormsAuthentication, but you can do the same thing with any cookie based authentication scheme (although I do not recommend rolling your own, you will almost certainly make security mistakes).
Some people think that storing a flag in Session is good enough. Do not, under any circumstances, ever use Session to store authentication information. Session cookies are not encrypted and are easily stolen and/or spoofed. Use a well known method.
The other answers might have already showed most of the details. But if we categorize carefully on IIS and ASP.NET levels, below are the differences you should pay attention to,
IIS Authentication
This occurs first, as HTTP packets arrive at IIS level first. IIS supports several ways,
Anonymous (the anonymous user account configured in IIS configuration)
Windows (browser side user)
Basic (browser side user)
Digest (browser side user)
How those authentication methods work at packet level requires you to capture network packets and dive into the conversation at that level.
The result of this authentication is that IIS generates a user token and passes on to ASP.NET pipeline.
ASP.NET Authentication
ASP.NET has several authentication methods of its own,
Windows (here ASP.NET trusts and interprets the user token IIS passes, and determines which ASP.NET user identity should be created and which roles it supports, without doing further authentication on ASP.NET level.)
Forms (based) authentication (where ASP.NET ignores the user token, and uses cookies or similar mechanism to build a high level authentication approach. On IIS side you usually set anonymous authentication.)
Claims based authentication, OpenID, OAthen and so on are similar to Forms based, where they don't care much about the user token generated by IIS.
It is possible to use non-anonymous on IIS plus non-Windows on ASP.NET side to set up the so called mixed authentication.
All the Authentication methods that require the user to input a Username and Password that you maintain are a form of Forms Authentication. This is because you are asking them to fill out a form (Username and Password) in order to authenticate them.
Read more about it Here or Here.
Edit: The answer provided by Mystere Man is much more complete and accurate than mine.
We are running a Saas ASP.NET 3.5 Web application using Forms authentication on a IIS 7.5 public server with protected content for thousands of users. We also have some subapplications running ASP.NET MVC 2.
Usernames and passwords are stored in our database and every user has roles and groups attached, with privileges and access rights defined.
Now we have been asked to also facilitate for simple SSO login via Active Directory so that users do not have to enter username and passwords twice to login. These users will originate from different networks and domains.
No user "sync" should take place from our servers to LDAP serves. We are not sure that any communication with LDAP is needed since all users will be created in our system and maintained there. Forms authentication will be used for most of our users.
From here on we are unsure which is the best path to choose. For our scenario what would be the "best practice" way to proceed?
The simple answer is SAML. It is considered the "best practice" and many large SAAS providers support it.
SAML protocol defines the single sign on flow between multiple systems. It establishes trust between systems using certificates. Your application accepts an assertion containing attributes (user id, name, email address, etc.) from other systems. Your app will map the user into your user store.
In .NET world there are several options. You can find a library that implements SAML (ComponentSpace has one) and hook it into ASP.NET authentication. You can create your own using Windows Identify Framework (WIF). Here's the boatload of WIF videos http://www.cloudidentity.com/blog/2010/06/23/ALL-WILL-BE-REVEALED-7-HOURS-RECORDINGS-FROM-THE-WIF-WORKSHOPS/. You can try IdentityServer http://thinktecture.github.io/
Depending on how secure your app must be, you can opt for a simple option of passing user id from trusted networks using a simplified method. I've seen apps that allow user id to be sent via URL parameter or form field. Of course, this is horribly insecure, and you are taking on more risk, because the trust between two networks is not cryptographically enforced. You can mitigate it somewhat by checking referrer string or IP address (if you can isolate IP range of a corporate network for example). But you are still open to spoofing because any user can impersonate others by simply replacing user id within HTTP request.
It probably doesn't answer your question fully, but hopefully points you in the right direction.
I recommend looking into ADFS 2.0 it is very powerful in terms of claims mapping and works with AD: http://msdn.microsoft.com/en-us/magazine/ee335705.aspx
What you would make is a token consuming portion of your app that would receive and parse the final claims returned to your web server after the authentication loop.
I'm using a login form to authenticate users.
FormsAuthentication is right out as it stores sensitive user/role membership in either client-side in a cookie or within the URL. Within the URL is a huge security risk, so I won't even get into that. With the
FormsAuthentication cookie, this creates problems with a) security where the client is in the position of dictating it's own roles; and b) way too much data stored in cookies. Since I'm gaining nothing through security and loosing out big time on the size of user data storage, I'd rather just work with Sessions.
I'd like to reuse something like FormsAuthentication for all its basic login form-handling features. But i would rather have it store user data server-side in perhaps Session rather than client-side all stuffed into a single cookie. I'd rather just authenticate against a Session token of some sort.
I have no database and local disk storage of user data is forbidden. I rely on a 3rd party authentication service provider, and a requirement is that I must reduce chatter with this service. Thus, sessions for temporary storage of user info. Sucks, but that's not necessarily the problem I'm asking about. Also, a requirement is that I must set/use HttpContext.user and likely Thread.CurrentPrincipal for use later on in such things as AuthorizeAttribute, for displaying user info in views, etc.
So FormsAuthentication stores all user data client-side in a cookie. Whereas Session stores all data server-side and just relies on a simple client-side token cookie. However, Session is not available anywhere during the asp.net startup and authentication steps. Is there an equivalent forms "membership" provider that stores all data in Session server-side instead of client-side?
If there is no Session equivalent...
Where do I set HttpContext.user and Thread.CurrentPrincipal to make both values available throughout the rest of both MVC apps without interfering or messing up other MVC components?
Hinging on #1, is Session available at that entry point? If not, how do I make it available so I can create the Principle/Identity object using the data stored in Session?
This can't possibly be a unique requirement. Are there libraries already available which handle this?
Session stores information in a client-side cookie too! (or in the URL if cookieless).
If you want to authenticate a client, he'll have to provide some kind of credentials - usually an encrypted token in a cookie once he has logged on. If not a cookie, then what do you propose?
You should use FormsAuthentication. The sensitive information stored in a client-side cookie is encrypted using a key that should only be known to the web server. "the encryption methods being public knowledge" doesn't mean that you can decrypt the data without access to the appropriate cryptographic key.
You mention "roles" and a "third-party authentication provider". If your third party is also providing roles (i.e. an "authorization provider" as well as an "authentication provider"), then it would be reasonable to cache roles obtained from the provider on the server. Session is not available when a request is being authorized, so the best solution is to use the Cache (System.Web.Caching.Cache).
Personally I would encapsulate this in a custom RoleProvider. The custom RoleProvider would implement GetRolesForUser by getting roles from the third party on the first call, then caching them in Cache.
Not sure if I like what I'm about to suggest, but you could do the following:
Leverage the Application State or System.Cache as a global storage for user credentials.
Use an InMemory database (like RavenDb) which can also have encryption (in memory, I believe).
Using the Application state as a place to storage relatively common / frequent stuff I think is not a great place because of
Scaling / locking issues? <-- just a gut feeling.
Permenant data? so you have users in the website's memory .. then the website crashes or recycles, etc... what happens now to that data?
RavenDb is awesomeballs - go.use.it.now.
I understand that you are not storing anything locally, so whenever a user hits your system, you need to refresh your inmemory cache, etc. Fine. A pain in the f'ing butt , but fine none-the-less. (EDIT: unless the data has been cached in memory .. that is)
Anywys, two suggestions.
ProTip:
Oh! move away from role based shiz and start using Claims based identity stuff. Yes, it still works with IPrincipal and HttpContext.User, etc. So all previous code is NOT busted. But now it's baked into .NET 4.5
Awesome Video on this for you, me, everyone!
Finally - bonus suggestion
A nice package that auth's with either Facebook/Google/Twitter. You said you're keeping the user cred's on another site (good move!). If you're using other providers, then stick with DNOA or SS.
GL!
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)....