We have started building an asp.net mvc application. Application will consist with one main database with users, projects, common tables etc... and many databases (all with the same structure) with a data relevant to a particular project. Use can have some global roles (stored in a main database) and some project specific roles (stored in a project database) and each user can be linked to many projects.
My goal is to build an authentication system that will support classical username/password authentication and also an OpenID authentication (we are using DotNetOpenAuth for this purpose) and authorization system that will support the roles system which I described above.
But I run into several question:
1.) I think that we should support both (username/password and Ppenid) authentication options for a single user, so that username/password users won't need to create additional account when they decide that they will use an OpenId and I think that we should support several OpenId's for a single user like SO does (if some provider is down).
2.) I think that the best database for this would be:
table Users (UserId (PK), LastActivityDate)
table UsernameLogins (UserId (PK,FK), Username, Password, IsApproved, IsLockedOut, LastLoginDate, LastLockedOutDate, etc...)
table OpenIdLogins(OpenIdUrl (PK), UserId(FK),LastLoginDate)
table Profiles(UserId(PK,FK), DisplayName(Unique), Email (Unique), FirstName, LastName, Address, Country, etc...)
table Roles(RoleName (PK), RoleType(1=GlobalRole,2=ProjectRole).
table UserRoles(UserId(FK,PK), RoleName(PK)).
3.) Should I create my own providers (MembershipProvider, ProfileProvider, RoleProvider)? Its seems that MembershipProvider is not so appropriate for an OpenId authentication (and of course I can only support just basic methods (GetUser,ValidateUser))? Should I implement MembershipProvider just for username/password logins? I think that ProfileProvider and RoleProvider wouldn't be that hard to implement? Should I just use FormsAuthentication and use my own "services"?
We are also using NHibernate and Spring for DI.
Any advice will be appreciated.
Thanks!
1.) I think that we should support both (username/password and Ppenid)
authentication options for a single
user, so that username/password users
won't need to create additional
account when they decide that they
will use an OpenId and I think that we
should support several OpenId's for a
single user like SO does (if some
provider is down).
That seems reasonable. I like how you're designing in for users to have multiple OpenIDs. StackOverflow limits users to just two, but users often have more than that and may want to bind them all. I think username/password is a fine option if your target audience demands it OpenID. StackOverflow is a great example of how simple login can be when its pure OpenID. It can make login less busy to not offer username/password. But again, providing both as options seems most customer-focused since it gives them choice. A future version of DNOA will offer an integrated version of the InfoCard Selector into its OpenID login system so that you can even accept InfoCards directly, but have it look and feel just like an OpenID so your system won't require any changes.
2.) I think that the best database for this would be: <snipped/>
That looks like a reasonable schema. As you've discovered, separating the credentials tables gives you the greatest flexibility.
3.) Should I create my own providers (MembershipProvider, ProfileProvider, RoleProvider)?
MembershipProvider certainly doesn't fit OpenID very well. If you were only supporting OpenID login I'd say throw it out and don't bother implementing your own. The RoleProvider works perfectly with OpenID so that's a keeper. I've heard from others that ProfileProvider needs a MembershipProvider in order to function. I don't know if that's true. But ProfileProvider requires that you use the ASP.NET Membership SQL database schema, which I think is poor if you can write your own db schema which you've done. And if you're writing your own db, storing additional data about your users should be trivial so you shouldn't need the profile provider.
If you go with both username+password and OpenID, then having a MembershipProvider that you implement yourself would likely be possible, but in my experience most MembershipProviders that include any OpenID code are kludgey and even have security holes. So I'd still avoid the MembershipProvider if OpenID has any place in your system.
I wonder...is support for multiple OpenIDs that important. It seems like this is more the role of the OpenID provider. For example, I use ClaimID and I get what essentially amounts to "identify forwarding" (in the sense of email forwarding) so that I can rebind it to different identities. Now I don't rebind providers frequently but a provider could do this (i.e. when you get redirected to their login page they could ask you which identity you'd ultimately like to present). So the question is...is this really the applications job to implement?
Related
I am developing a WebAPI over my already existant MVC application, using the OAuth2 authorization system.
This API will allow my clients to request my users information. Currently, my users are stored in the Identity tables (ASPNetUsers). In my application, they are registering, logging in, etc... with the help of the Identity classes and methods.
The problem is here : I want to manage my API clients accounts, in an "Identity way", so I can authenticate them when they ask for Access Tokens. But I can't use the current users tables, as there is no common points between my clients and my users.
The perfect solution would be to have two Identity tables : one for my users, and one for my clients, but after my long-time searches, I figured it was not possible, or it would be a mess, at best.
I would not use ASP.NET Identity as a way to manage OAuth2 registered client applications. Even though some client applications (confidential) are indeed issued client credentials that's probably the only thing they share with a username/password user identity. It's a completely different thing and as such it should be managed and stored independently.
If you're thinking that this sounds like a lot of work, you're absolutely right. It isn't trivial to implement a custom username/password authentication that proves secure and implementing an OAuth2 authorization server is many times as complex.
If you really want/need to go that route then some mandatory reading:
The OAuth 2.0 Authorization Framework
OAuth 2.0 Threat Model and Security Considerations
JSON Web Token (JWT) (assuming you choose JWT as token format)
If you're still evaluating all your options I would also consider the possibility of delegating all the authentication/authorization work onto a third-party, Auth0 comes to mind, but I'm biased because I work there.
This is not like other questions you might find similar. My issue is way bigger.
Scenario:
I have 3 websites. All of them have a common database for authentication and stuff.
Problem is that i will need to expand to 2 more sites, which means more maintenance in login screens and so on. So i will dedicate time to make a "central website" to manage users, access, etc.
Also, Need to implement OpenId for Microsoft Works accounts (ie, Azure tenants).
DDBB User Model: (Simplified)
All users are in the same central database. Which does not contains
anything non-user related.
User is personal on all applications.
Users can have different Roles
Each "User-Role" is mapped to an application, a server and a
database.
Problem:
Created a site in AspNet Core, without any authentication done so I can do it myself since I found that mapping Aspnet Identity tables was no-go because of incopatibilities and overriding is way to complicated, specially when dealing with Managers.
So, Tried and got working a simple Authentication page using HttpContext.Authentication.SignInAsync and CookieAuthentication. Which works well and there is no need to use any of the Identity's implementation (which is not compatible with my backend).
But then I added UseOpenIdConnectAuthentication to have the OpenId auth, but I have no idea how to use it since its suposed to work out of the box when using Identity and when checked documentation they use this code in an controller action: signInManager.ConfigureExternalAuthenticationProperties and I do not have any SignInManager since Im not using Aspnet Identity.
Questions:
Is coping the source of ConfigureExternalAuthenticationProperties to make it work in my site an aceptable solution?
Should I continue to override all SignInManager methods and also probably implement other classes to make Aspnet Identity work with my model?
Tried Mapping the properties to my columns just to test it out and it gave me non debuggable errors, which i dont like to even think about the problems this can give me in the future. For example one error was that it coudnt parse byte[] to string.
How can I implement Microsoft Work Accounts authentication and Database authentication in the same AspNet Site?
Bonus topic
Recently I feel like programming is becoming Configuring instead of coding. Is it just me? Are we now Professional Configurers?
Thanks
I'm working on an MVC4 site using SimpleMembership to handle user accounts and role based authentication. We have another site and we'd like to implement a single sign on system allowing users from the existing site to log in to the one I am building. What would be the best way to achieve this and hopefully leverage to the existing roles based authorization I'm using on the MVC4 site. Is it possible to have multiple membership providers (i.e. use the built in one and if the user is not found, attempt to authenticate via a custom provider that I'll write (once I work out how!). Or would it be better to abandon the built in membership/roles and roll my own?
I also thought of letting WebSecurity check the local database and if the user is not found, query the 2nd database and if the users credentials are valid, create a local account for them. One issue with this approach is if a user called Fred registers on the MVC site, and then a user from the other site called Fred logs in, we couldn't create them a local account with the same username. We could prefix/suffix the username with some text to indicate that they are from the other site but then we lose the single sign on feature.
We will also want to integrate AD authentication for staff in the future.
So essentially I'm looking for the best way to authenticate users from multiple databases and keep using roles based authentication?
I've also done a little digging was wondering if ADFS might be useful for this.
Any help or advice would be greatly appreciated!
I recommend the use of an Identity server to handle all your login request and switching to a claim based authentication instead of a role based authentication if you can.
I personally went with Thinktecture IdentityServer
pluralsight.com have a good course on it.
Thinktecture IdentityServer is build on top of simple Membership and it supports multiple protocol such as
WS-Federation
WS-Trust
OpenID Connect
OAuth2
ADFS Integration
Simple HTTP
I recommend checking it
Good Luck
There is so much information and terms here I find it hard to start think about users. What options would I have for creating a user-based ASP.net MVC 3 web app? I've read of membership, providers, authorization, authentication, session, cookies, roles and profiles, but I can't seem to get a grasp on the big picture of how user-things are handled.
What are the pros/cons of using a built-in microsoft solution here? What is it even called?
Can I use my own database only (I want to work database first)?
In my mind I think like so: I have users and roles in a database. Users have roles. I want to deny access to some actions depending on if the user is logged in and has a specific role. Am I over-simplifying the issue? Where should I start?
At the moment I'm thinking of doing a 100% home brew system like when I was developing using PHP but since there's so much info I feel like that would not be a good approach here.
You want users and roles, i.e. you want to authenticate users and authorize them with privileges using roles. I would highly recommend not rolling your own, as you would in PHP. Instead, I recommend using the .NET "Provider" services -- specifically, the MembershipProvider (for authentication) and the RoleProvider (for authorization).
You can still use the Providers with your own db, they are not exclusive to or exclusive with code first. However, I would recommend NOT storing application-specific user information in the Provider's user or member tables. Instead, you can have your own code-first User, and link it to the membership system through the user's username.
The reason I recommend this is because it reduces the amount of work you have to do. You need not worry about encrypting or hashing passwords -- the provider does it for you. You have full API to control your users and roles through the System.Web.Security namespace.
As for Profiles, this is a separate Provider service that you do not need to use. It allows you to store information about users whether or not they have registered for a user account in your system. Technically you can have "anonymous users", but anyone who has created a password-based login is instead referred to as a "member".
Regarding cookies, authentication of a user in .NET is done through the FormsAuthentication class. After you have authenticated a user using System.Web.Security.Membership, you can call FormsAuthentication.SetAuthCookie to write their authentication cookie. This fully integrates both the User and their Roles into the Controller.User property, which implements the IPrincipal interface. You can use this object to get the user's name, and find out which roles they are in.
Reply to comments
I answered a very similar question here. Basically, it's up to you whether or not to have the membership in a completely separate db than your application, but I consider it good practice, because I have done this quite a bit and I have no complaints. Especially if you are using code first, since you can lose your entire db if you use the DropCreateDatabaseIfModelChanges or DropCreateDatabaseAlways initializers.
There is also a new membership provider. I think the NuGet package is called "ASP.NET Universal Providers", and they are in the System.Web.Providers namespace instead of the old System.Web.Security namespace. I haven't had a chance to work with them yet, but from what I gather, they are more compatible with code first. For one thing, the tables aren't named like aspnet_Foo, and there are no views or stored procedures created in the db. The table names are just normal dbo.Users, dbo.Roles, etc.
As for linking the provider users with your app (content) User entities, see the answer I linked to above. The easiest way to do this is to just have a field in your content db for UserName, and link that to the provider db's UserName. No foreign keys necessary, since you integrate them at the app-level, not the db level.
I think you should first start with built-in solutions, they're easy to extend if someday you'll need something more (even if to write a good providers for authentication isn't really trivial. Start reading this article, it's a good start point).
I don't think to write everything here is a good idea, it's a big topic and I should simplify everything too much so I'll post some links I found useful.
Just to start, with text from MSDN:
Authorization determines whether an identity should be granted access to a specific resource.
Authentication is the process of obtaining identification credentials such as name and password from a user and validating those credentials against some authority.
Imagine users and roles as Windows users and groups. For example a web-site for forums may have a user named AUser with following roles: User, Editor, Moderator. In that web-site they may grant a set of allowed actions: User may enter new posts, Editor may change posts of other people and Moderator may close or delete posts or topics. In this way single web pages don't need to know users but just roles (the DeletePost method of PostController may be decorated with [Authorize(Roles = "Administrator, Moderator")]).
Start reading this very introductory article, it provides additional useful links.
I have a Rails app acting as an OAuth 2.0 provider (using the oauth2-provider gem). It stores all the information related to users (accounts, personal information, and roles). There are 2 client apps that both authenticate through this app. The client apps can use the client_credentials grant type to find users by email and do other things that don't require an authorization code. Users can also log in to the client apps using the password grant type.
Now the issue we're facing is that the users' roles are defined globally on the resource host. So if a user is given an admin role on the resource host, that user is admin on both clients. My question is: what should we do to have more fine-grained access control? I.e. a user can be an editor for app1 but not for app2.
I guess the easy way to do this would be to change the role names like so: app1-admin, app2-admin, app1-editor, app2-editor, etc. The bigger question is: are we implementing this whole system correctly; that is, should we be storing so much info on the resource host, or should we denormalize the data onto the client apps?
A denormalized architecture would look like this: all user data on the resource host, localized user data on each client host. So user#example.com would have his personal info on the resource host and have his editor role stored on client app1. If he never uses it, app2 could be completely oblivious of his existence.
The drawback to the denormalized model is that there would be a lot of duplication of data (account ids, roles) and code (User and Role models on each client, separate management interfaces, etc.).
Are there any drawbacks to keeping the data separate? The client apps are both highly trusted--we made them both--but we are likely to add additional client apps, which are not under our control, in the future.
The most proper way to use oAuth and other similar external Authorization methods as I see it, is for strictly Authentication purposes. All the business/authorization logic should be handled on your server part at all times, and you should always keep a central record of the user, linking to the external info per external type of auth service.
Having a multilevel/multipart set of access, is also a must, if you want your setup to be scalable and future-proof. This is a standard design that is separate from any authorization logic and always in direct relation to business rules.
Stackoverflow does something like this, asking you to create an actual account on the site after you login using an external method.
Update: If the sites are really similar you can subset this design to an object per application that keeps the application specific access rules. This object has to also inherit from a global object that has global rules (thus you can for example impose a ban application-wide or enterprise-wide).
I would go for objects that contain acess settings, and roles that can be related to instances of both application level settings and global settings only for automating/compacting the assignment of access.
Actually you can use this design even if they are not too similar. This will help you avoid redundant settings and meaningless (business-wise) roles. You can identify a role purely by the job title/purpose, and then impose your restrictions by linking to an appropriate acess settings setup.