I can't imagine that there doesn't exist an efficient, lightweight, secure authentication and authorization library for ASP.NET applications that is easy to use in e.g. your controllers and views. I read tons of articles and I performed a zillion searches, but did not find one yet. Does anyone know of such a library? Or did anyone create one himself and is willing to share?
The ASP.NET authentication system is mainly based on the Username rather than on UserId. I really don't understand that. Imagine you want to create a blog with comments. A user can register and post a comment. Two well-known MVC examples (Nerddinner and MVC Music Store) use the default asp.net authentication system (membershipprovider / identy / principal etc.) and use the Username to store the user that belongs to some object, e.g. "HostedBy"-field.
To me, this seems not a very good practice:
It's not possible to change username without having to change all the related records.
Why not us an int as Id? You need just 8 bytes to store 16 million users. Unless you limit the username to 8 byte-characters, it is less efficient in terms of storage space.
A string-based relationship seems not very efficient, as string based lookups are slower than integer based lookups.
Oke, I can imagine why you want to use a Guid and not an int, because that is virtually impossible to guess and to remember and that could increase security in some way; if that's the reason, that's fine to me.
But, then remains the question why the IIdentity interface makes just the Username available and NOT the UserId. If you use the UserId as foreign key, it's hard to e.g. fetch a list of all the posts of the current logged in user: you always need a database lookup to fetch the UserId that belongs to the username.
Another thing I wonder about is that the authentication system seems rather bloated. My best guess is that at at most 90% of the users will use an authentication system for just one application. So, why create default functionality to make it capable of serving multiple applications? (the application column in aspnet_Users).
If you don't care about these things, it's might be allright, but, I want to prepare for 16+ million users, don't you? Or, I want to server my pages under 50ms... So.. why the heck did Microsoft build the default authentication system this way? It seems pretty bloated and crappy to me.
A related question (which doesn't give answer to mine):
How can I access UserId in ASP.NET Membership without using Membership.GetUser()?
OK, you dislike the ASP.NET Membership Provider. If you're an NHibernate shop, then you could take a look at Rhino Security by Ayende Rahien.
Related
I have an ASP.NET 5 (RC1) application for which I am trying to set up authentication and authorization. However I am confused and overwhelmed by all the varying authentication and authorization information online in as it pertains to this platform. Much of it seems either hopelessly out of date or simply doesn't seem to apply in this particular usage scenario. Right now, I'm not even sure what the right 'terminology' to use for the question I am trying to ask, but I digress.
What I am trying to accomplish is a system whereby users are authenticated/authorized via Azure AD (B2C?), with additional user profile information stored in a database. However, the user context in the controllers is accessed in a consistent way using what I presume would be a custom ClaimsPrincipal/ClaimsIdentity? I would imagine this should be as simple as adding an 'authorize' attribute or something similar and accessing the ClaimsPrinciple.Current.Claims.
I have used ASP.NET Identity in the past, but many of the examples I have found aren't using that. Most are simply using the UseOpenIdConnectAuthentication middle-ware. I see that ASP.NET Identity is still available but I'm not sure it applies in this scenario. I also found a couple posts on here suggesting using a custom ClaimsIdentity to accomplish this, but I am having trouble finding useful up to date examples. BTW, I realize that much of this "profile" information can be stored as custom attributes in azure ad but the way some of the information is used within the application prohibits all of it from being in azure (i.e. EF linq joins and such).
Please, tell me if I am even close on some of this. I know this is a fairly new platform and the information is sparse, but certainly I'm not the only one asking these questions.
Just calling out an excellent article Identity management for multitenant applications in Microsoft Azure.
A lot of your questions are answered there.
e.g. you can augment the claim in the OWIN middleware AuthenticationValidated event.
ASP.NET Identity is claims-based in that the attributes are delivered as claims but authentication is on the DB, not via external IDP like Azure AD.
B2C is a special case in Azure AD - used for many (millions!) external users who can self-register and self-manage e.g. SSPR.
B2C uses a separate tenant to the normal Azure AD one and the users have no access to things like O365 or any SaaS applications.
Single Application Page Asp.net MVC 4 temlplate uses default database to check Login and Register but I want to use my existing database in my SPA application. There are some table to store info like default database and some table to store other info in my database. So how can I do this? or I just have to use default database for Authorization and use my database to do business?
There are, as always several ways to accomplish this task.
Microsoft shows you an example using ASP.NET Membership and Roles as it's a powerful way to accomplish what you want, and it even provides you with a sample Database for that to work.
You have the ability to override all the methods that handle membership and roles in this way, you benifit from using ASP.NET Membership & Roles and use your own Database (or anything to keep your user information in a common place, like text File or Xml, you decide!)
For this, you can see my answer on how to create your own Membership Provider:
Custom MembershipProvider in .NET 4.0
I suggest that you read this answer to the end, as I have added a Video Tutorial on the subject that might help you seeing thing this in a different perspective and how easy is to implement this.
Or you can simple discharge the Provider and do and use your own method, like, validade user and password and keep a Session throughout the user livecycle that let you know the user information and if he's logged in or not...
As throughout this late years, Microsoft suggest that you use their way, but you have always the freedom to do things your way.
I am building a multi-tenant site with MVC3. Prior to this project I had never touched either the .NET stack or web development in general, so as you can imagine my domain knowledge is somewhat lacking.
I'm still using the default AccountController architecture, but I pretty quickly determined that I didn't want to use aspnetdb.mdf for authentication, as its design is pretty different from my requirements. I do want role-based authentication, so I ultimately wrote custom User and Role classes as code-first Entity classes and used this tutorial to set up a custom MembershipProvider and RoleProvider.
Everything works fine at the moment, but as I'm building the multi-tenancy functionality it's getting messier. Based on this example, I am using a custom extension of Controller which keeps track of which tenant is using this session, and all my controllers extend this class instead of the base Controller class.
All tenants are using the same database. Each entity has a Tenant property that identifies who it belongs to.
So, here's the problem:
Usernames do not need to be globally unique. Only the combination of username and tenant must be unique. Thus, ValidateUser needs to know the username, password, and tenant. Since my custom MembershipProvider is not a Controller, it doesn't know which tenant is using the session, and the ValidateUser method only accepts username and password so I can't pass it that information.
Furthermore, pretty much everything MembershipProvider does besides ValidateUser is already implemented in a UserRepository class, which that tutorial told me to make. I'm rather fond of the Repository pattern, and it's way more convenient than adhering to MembershipProvider's interface, but now there's a massive conflict of interest between UserRepository and MembershipProvider.
So, my question:
Do I need to use MembershipProvider, or even Membership, at all?
It seems like everything MembershipProvider does would be performed more conveniently by my repository class. At this point all I'd have to do is write a new Authorize attribute that doesn't rely on Membership, and everything should work without any MembershipProvider at all, right? If I don't drop Membership I'm forced to completely mutilate my MembershipProvider implementation to the point that it barely resembles the original interface anyway.
...Either that or Membership does a ton of things I'm unaware of and removing it is blatant stupidity. That is also a distinct possibility.
No, you don't need to use Membership, but consider for a moment exactly what Membership is. Membership does not involve your users names, or addresses, or other information. Membership is strictly related to the login account of the system. It only handles details with creating, validating, updating, or deleting the information needed to login. That's it.
Likewise, the Role system is only assigning a role name to the user.
Ultimately, Membership and Roles are just implementations of the IPrincipal interface. While FormsAuthentication is an implementation of the IIdentity interface. These work together so that you can utlize the built-in ASP.NET Authorization and Authentication system.
Membership actually does have the concept of multiple tennants. This functionality is accomplished via the "ApplicationNane" field of the aspnet_users table (also settable in the Membership class itself)
From the documentation on the Membership class:
The ApplicationName is used to identify users specific to an application. That is, the same user name can exist in the database for multiple ASP.NET applications that specify a different ApplicationName. This enables multiple applications to use the same database to store user information without running into duplicate user name conflicts. Alternatively, multiple ASP.NET applications can use the same user database by specifying the same ApplicationName. The ApplicationName can be set programmatically or declaratively in the configuration for the Web application.
Now, this is designed to typically be set in the Web.Config and stay the same for the life of the app, but I see no reason why you can't use it to specify which tennant you want.
The only issue here is that Membership.ApplicationName is static, which means it's shared by all threads running in the App Pool. However, if you use some kind of lock around accessing it, then this shouldn't be a huge issue (though it could affect scalability at some level).
This would basically allow you to use the standard, out of the box membership provider without any changes. You just have ot make sure to guard the access calls.
You don't have to use the membership provider at all. Its simply provided as a quick and consistent way to get up and running. Some choose it because it supports multiple databases (universal membership providers include azure as well as sql ce, express, and full) but for others trying to map it to your applications rules can be more difficult than the <5 lines of code it takes to authenticate and issue your own forms auth ticket.
With that said I'm assuming you are using forms authentication. You can simply issue the ticket yourself. I would still program against an interface for this which the default MVC template should have, so simply add in a new tenant id.
With that said, I'd consider having unique names. It ensures you don't 'forget' to do an additional tenant check somewhere else in the app and tenant1\userBip and tenant2\userBip surprisingly end up stomping on each others record at some point.
True, testing should uncover this - if testing is complete : )
Ok, I'm new to web development, so I might be getting some of these terms wrong. I apologize in advance.
I am having trouble understanding the different elements of authentication. Every method seems to be advised against by someone, though not always with clear reasons. I am building a web app for a company that will have access to a database, so I would like to make sure it is secure.
So the there are three places I have seen commonly used to store information.
FormsAuthentication.SetAuthCookie(). This stores a session cookie that will exprire with the browser, and nothing sensitive is on the client. However, it can only store one value. This stackoverflow answer shows a method of storing multiple values here, but the guy who gives it says not to use it, though not why.
FormsAuthenticationTicket. I don't know where this information is stored, but it allows for a simple method of storing multiple values. Securing it, according to the documentation requires calling Encrpty() to store, and decrypt() to retrieve. This seems wasteful, but what do I know.
Session["SomeRef"] = new CustomObject(). The second answer in this question explains how to do this, but a comment to it calls it dangerous because it can be stolen. This looks like the best method to me, because the information is still stored on the server, and can store multiple values.
I cannot find any comparisons for these methods, or good explanations on the "best practice" way of storing multiple pieces of information after authenticating a user. The information is just the User's name and their userId.
Here is some further clarification to help you decide.
SetAuthCookie can be implemented in a way to store multiple values. In practice, however, you usually can't store enough to avoid a database lookup. It's best to store the user name (unique identifier) and load more information during the request. As your question suggests, you shouldn't store sensitive information on it. You should assume that all information sent in a cookie can be decrypted and read and you should take precautions that that information can't be used maliciously. All session cookies can be stolen and I'll explain why in a moment.
FormsAuthenticationTicket is the same API as SetAuthCookie but at a lower level in the Framework. With SetAuthCookie, Encrypt() and Decrypt() should be happening anyway (it's the default configuration.) It's not wasteful but use method 1 instead because it's easier.
Session has some limitations. Notably, by default it's process-dependent. That means that when the server restarts or more than one web server is involved, your session is lost and you have to authenticate again. It is the easiest to use and fastest when using the default memory session storage (InProc). You can use sql storage or a dedicated session server to overcome the process-dependency.
All three methods are considered dangerous for the same reason all cookie-based authentication systems are dangerous: because the cookie's value can be sniffed over wireless and reused to take over a session. This is known as sidejacking and it also applies to scenarios 1 and 2. The way to prevent this is to implement HTTPS. Then, the cookie transimission (and everything else) is encrypted at the network level and can't be stolen.
TLDR; Use SetAuthCookie and HTTPS
NOTE this answer has been edited several times for clarity.
I came up with an interesting way to solve the following problem and I want to know if there is a better way to achieve my objectives.
Basically, I'm creating a basic cms system users can register for their own microsite and have their own users. I'm using the asp.net membership api.
I wanted a way to isolate users of the various microsites from eachother so that a user authenticated with www.mysite.com/johns-site wouldn't also be authenticated with www.mysite.com/pauls-site.
I also wanted a way to associate a username with a microsite so that if a user is registered as bob on one site, it doesn't stop another user registering as bob for a different microsite.
To achieve this, I noticed that in the asp membership tables a user belongs to an application. Every time I receive a request, I have a method that switches the applicationName in the web.config based on the url.
This does meet my objectives in an easy way but feels a bit hacky. Is there an alternative way to switch applications for the membership provider?
It is possible to get/set the ApplicatioName property at run time however according to the below MSDN post it is not recommended as the property is not thread safe i.e. if multiple users are creating accounts for different applications at the same time it may not correctly allocate the ApplicationName per user.
Syntax:
Membership.ApplicationName = "MyAppName"
OR
Membership.ApplicationName = "MyAppName";
Further reading:
http://msdn.microsoft.com/en-us/library/system.web.security.membership.applicationname.aspx
Note:
You are updating the contents of the web.config file from the application code? If so this is most certainly "hacky". Plus editing the web.config will drop any active sessions (if your app uses session state of course).
I agree, it is a hack that will likely make you pay at some point.
The proper way to accomplish this would involve each virtual directory (or microsite as you say) each defining a <membership> element with the same connection string but different applicationName attribute.