Best practice to join nhibernate and ASP.NET membership/role/profile services - asp.net

I've got a generic ASP.NET (MVC) application, that uses NHibernate as the model persistence layer, and ASP.NET Membership/role/profile services as the user management layer.
The question is what can be considered as the best practice to create linkings between the domain data and the users. (For example is I want to create a forum system I want to link each topics/posts to a specific user, and want to display the user at each request).
These are the posiibilites I've been thinking of:
Store the user ID in NHibernate (like having a Guid column in all your domain classes (Posts, Topics etc.) that needs to reference a User) and use GetUser each time you need the name of the user from the guid (which might result in n+1 queries)
B variant: Alternatively store the user name too.
Use the same database, and create a read-only NHibernate maintaned domain object User, that maps to the same data as the M/R/P services do.
Forget about M/R/P and create a separate user management service based on NHibernate
Forget about both and use J2EE/RoR/merb/DJango/etc. (please don't pick this option :) )
other...

I would go for step 2 (almost, as it does not necessarily needs to be readonly) and create a custom membership provider for NHibernate.
To save time you can use an existing one like the one from Manuel Abadia.
With that you keep the full power of NHibernate (lazy loading, etc.) and enjoy M/R/P services too.

There is also a NHibernate based Membership provider at CodePlex

4 guys from rolla have an excellent post if you want to buil your own provider on top of the asp.net membership API : https://web.archive.org/web/20211020114106/https://www.4guysfromrolla.com/articles/110310-1.aspx

Related

ASP Core. Best practices for multiple identities

env: Asp Core, Entity-framework
In my system I have two types
[Table("User")]
ApplicationUser : IdentityUser<Guid>
[Table("Customer")]
Customer : IdentityUser<Guid>
Both entities(Customer and User) have many different fields, what makes using only one table in a Database not correct. And both entities must have possibility to do sign in.
As I found ASP Net can have only one identity setup.
Question: What is the best way or best practices to make this stuff work?
I suggest you not try to mix or unify Identity of application user and meanings of application user from another boundary contexts of you application.
Identity record of application user is his representation from security perspective, and it is used for identification/authentication of user. So it contains user security data, its access roles and other security claims. Any Identity record can have very specific access right based on his roles and claims and usually it is enough.
If you need to represent application user from another perspective (as your employ, or as you customer, maybe as guest record, etc.) then it is better to create another table (Employees, Customers, Guests , etc.) for it in another DbContext (not in Identity context). It will give you possibility not to mix their conceptual borders. Who knows, maybe at some moment you will decide to create separated microservices for each boundary context and Identity will serve them all as another microservice.
If you asking now yourself how to organize such parallel storing of interpretations of the same application user, then there are different approaches. But for example:
When user is registering you create Identity for him
When he is logged-in he use his Identity data for authentication
But when he create his first order you create Customer record for him that has same Id as his Identity, or has foreign key to Identity, or... the rest depends on your needs and business logic.

ASP.NET MVC 5 Identity 2.0 & OWIN Two Factor Authentication by using existing DB

I've just started with MVC after working on Web Forms for 4 years. I've watched few videos explaining the architecture/fundamentals and I'm now able to replicate few modules of my old project with MVC5 using EF6.
I've a SQL Server DB containing tables such as Albums/Artists/Titles/Reviews and he User Table. I was able to work with the first set of tables using EF6 just fine including inserts/deletes. The prev project I had implemented custom Web Forms authentication using BCrypt by storing the details in the User table and later doing the validations and setting the auth cookie.
User table has details such as UserId, PWHash, EMail, FirstName, LastName. The UserId is a FK in the Reviews table and few others.
The implementation I'm hoping for is as below:
1. Login screen accepts credentials and validates with existing User table.
2. If valid, move to the 2FA screen(eMail/SMS).
3. If valid, then allow access to application.
Most of the tutorials say how to extend the attributes such as FirstName/LastName but do not say how to use an existing DB. I'm planning to use bcrypt/scrypt to encrypt the sensitive details.
I've gone through MVC 5 & ASP.NET Identity - Implementation Confusion but id doesn't have all the answers to my queries
I just need the starting point on how to plug the existing DB instead of using the dbcontext provided by default
Personally I find the documentation quite frustrating as well when you move away from th conventional, so you may be in for a world of pain.
The easiest way would be to fully take control of the authentication process yourself, utilising FormsAuthentication
However, if you want to leverage a lot of the out the box code, that has been delivered with MVC5 but against a custom database, or schema you will probably have to implement your own UserStore and maybe UserManager among other things.
The problem is, there is a lot to implement, so you are going to have a fun time guaranteed.
Have a read through this article on Custom Storage Prodivers to get a head start.
Good luck
If your app is using EF Code First then you can use your existing schema and plug in your own user. Look at the following example which shows how you can reuse your existing user information and plug it into Identity http://aspnet.codeplex.com/SourceControl/latest#Samples/Identity/CustomMembershipSample/Readme.txt
You do not have to inherit from the IdentityDbContext. You can directly use the DbContext. In this case you will have to override the onModelCreating to create the Users/ Roles tables and all the mappings between the tables.

Checking additional requirements during login? (MVC, forms authentication)

Background:
I'm incorporating the SqlMembership provider into an existing system where I'm building a web front end. The Membership database will be kept in a separate database.
Beyond the login account, there's an additional mapping between the accounts that needs to be in place in the main database in order for an account to be able to log in.
Let's say that this table gives the user the right to use the system.
My question:
I would like to somehow incorporate this into the provider. Is it possible without too much work? (Or is it better to keep it in the AccountMembershipService class?)
Actually regardless, I'm very interested in learning how to put additional login requirements into the provider.
I'm asking this because when I've been looking at creating a custom membership provider earlier it seemed at that time a little bit overwhelming.
In other words:
I want to understand how to extend the Membership Provider classes in general and how to extend the login method (ValidateUser) in particular.
Given the sample ODBC implementation It looks like one simply could subclass the default provider and override ValidateUser calling base.ValidateUser as the first step.
However it may or may not be that simple, and I'd be very happy to hear any first hand experiences from implementing or extending membership providers.
I wanted to do something similar, one of the requirements was to use an Oracle DB, so I implemented the OracleMembership provider, hence I could not waste my time rewriting the hole oracle membership provider (it works pretty fine), the second requirement was to use a custom authorization legacy system. So I realized that the Internet Application template which comes with the MVC 2 or 3 comes with a small implementation of the security for the site, specifically take a look on the AccountMembershipService class. You could move all of these elements out of the MVC app to a separate assembly so you could use it even on a client implementation. The AccountMembershipService uses the Membership provider as the underlying authentication system with the option of using FormsAuthentication.
So I recommend you to take a look on that implementation. You could put your additional authentication code there so your application would stay cleaner and your don't need to re-invent the wheel and you have the chance to add your own code.
best regards
In order to extend the membership provider make you own tables with one to one relationship with the main database and handle additional requirements through this table. Also while implementing and extending the default membership provider you may need to store extra information in authcookies you may get additional information from here , here and here
In GetUserCredentials you will do your stuff for additional checking and RoleID is some dropdown on your login page that you will receive in the post method of sign in.
FormsAuth.SignIn(userName, rememberMe);
ApplicationRepository _ApplicationRepository = new ApplicationRepository();
MembershipUser aspUser = Membership.GetUser(userName);
SessionUser CurrentUser = _ApplicationRepository.GetUserCredentials(aspUser.ProviderUserKey.ToString(), RoleID);
if (CurrentUser == null)
{
ModelState.AddModelError("_FORM", "Invalid Role ");
FormsAuth.SignOut();
return View("signin");
}

ASP MVC User Profiles

I've done MVC in the past, but I am new to ASP and ASP MVC. I really love the ease that ASP MVC provides me, so far, but I am having trouble figuring out how to get more control over the Users. By default, the MVC provides a minimal user registration form. I have looked around quite a bit, but I still have two questions:
How do I make the User data base a local database in my project? I think SQLEXPRESS is used to store the user values, in what seems like a magical process. How do I de-magic-ify this? I would like to have more control on the location of this database.
This leads to another question: How do I expand the User? I have been reading up on Profiles, but I am still confused about a few things. How do I prepare a Profile and link it with a User? What serves as the foreign key? And, in my controllers, how can I access various parts of the user like username, email, or even from the profile stuff like firstname, lastname (though I guess once when I have a Profile's database and a User's database locally, I can run sql commands to retrieve data)
I would really appreciate some pointers to the right resources, and/or best practices with ASP.NET
I would start by reading this official Microsoft article on extending the ASP.NET Membership API. It talks about creating extra tables for storing additional information about users.
The membership database
If you have an existing database which holds all your other website information, you can run the aspnet_regsql.exe tool to generate the necessary user tables. You will then need to modify your web.config and add the SqlMembershipProvider along with your connection string.
If you're creating a new project and don't have a database, start with a new MVC project which already has Membership enabled. Your database will be created inside the App_Data folder on first use, and you can take this and attach it to your SQL/SQLEXPRESS server. Then it's just a matter of changing the connection string to use a DB server rather than a local file.
Creating additional tables
This part is actually quite simple and consists of a few short steps:
Create a new table, i.e. UserProfiles
Add a uniqueidentifier column as your primary key, and add a foreign key to the aspnet_Users table
Add any other fields you want to store (Phone, Address, Gender etc.)
If you're using LINQ-to-SQL or the Entity Framework, you can simply drag the tables you need onto the designer, and you'll be ready to query the Membership tables.
Here's a little sample on usage
Add this snippet to your repository responsible for Profile/Account information.
public aspnet_User GetUser()
{
MembershipUser user = Membership.GetUser();
return db.aspnet_Users.SingleOrDefault(u => u.UserId == user.ProviderUserKey);
}
Then inside your models, you can get the user and access the other information stored in your UserProfiles table.
AccountRepo accountRepo = new AccountRepo();
aspnet_User user = accountRepo.GetUser();
string Address = user.UserProfile.Address; // bingo!
And that's pretty much it!
This is obviously a simple example, and you should be checking if the user is null and you could also create a class responsible for returning the necessary information about a user, implement caching, etc..
I would start from here:
Managing Users by Using Membership
Managing Authorization Using Roles
Also a great article series (18 articles!!!) is from Scott Mitchell at 4GuysFromRolla.
The ASP.NET membership model is desgned to have a pluggable architecture. You can write you own MembershipProvider implementation that best suit your needs.
Even if most of the samples you will find on the net regards ASP.NET web forms, there are only very small differences when used with MVC.
If you're still looking for insight into this, I just ran across the fact that in MVC 4 WebPages sites, there's a provider called the SimpleMembership provider. It gives more control to the developer of the Users, Roles and Membership info stored on websites. More here:
http://blog.osbornm.com/archive/2010/07/21/using-simplemembership-with-asp.net-webpages.aspx

How to implement ASP.NET membership provider in my domain model

In a website, I need to integrate membership and authentication. So I want to use the functionality of ASP.NET Membership, but I have other custom stuff, that a "user" has to do.
So I am sitting here with my pencil and paper, drawing lines for my domain model... And how can I best utilize the ASP.Net membership, but extend it to fill my needs?
Should I create a class that inherits from a MembershipUser and extend it with my own properties and methods (and save this in a seperate table). Or should I let the MembershipUser be a property on my custom User/Client object?
What would be a good solid way to do this?
I've thought about it and there are 2 ways that seem appropriate (of course there are more ways to make it work).
Custom Membership Provider
You change the membership provider to use your own and use your User object to store all the information.
The problem with this one is that it involves a lot of re-implementation of things that are already well handled by Asp.Net. The good thing is that you have a single User object with all the details.
Link from a Membership User to your User
With this method, you would use the original Membership provider to handle the user name and password, but you link your own User object with this one with something like the user name by using a service for example.
It's really easy to set up, you just need to create a service that would be used like this:
string userName = "Jon Skeet";
User user = new UserManagementServices().GetUserByUserName(userName);
I ended up writing my own membership-provider, and have implemented that in 3 separate solutions now. It is extremely simple and much, much more elegant than linking a user to a membershipUser (which I have also tried).
Read this...:
Create Custom Membership Provider for ASP.NET Website Security
And if you want to learn more, watch this video (with sourcecode).
I've extended MembershipUser and created my own version of the SqlMembershipProvider to map to my existing domain, and its working well, in production now.
MembershipUser is essentially a view over my User table. My extended MembershipUser class includes profile/account-style properties instead of using the default SqlProfileProvider system, which is a bit fragile.
I wasn't able to use the existing membership tables or sprocs, but wrote my own. For example, the SqlMembershipProvider uses a GUID as an opaque key, but the production system uses a plain old int. All of the dates are UTC, etc. too.
All of the extra User functionality is accessed via the User domain not via Membership methods.
HTH.
I'm currently working through the Microsoft ASP.NET 2.0 Membership API Extended article from CoDe Magazine which explains how to extend the membership API by writing a wrapper around the existing classes. Main benefit is that you can keep all the out of the box functionality and not have to rewrite your own as you would when implementing a custom provider. Source code is provided.

Resources