Customizing SimpleMembership Provider - asp.net-mvc-4

I am using simple membership provider in mvc4 application and I can see five tables generated for that. In that i can see username and password are stored on different tables. I want to save username and password on the same table with some custom fields. So I am creating my own Membership Provider by inheriting ExtendingMembership Provider. I have some queries over that.
My application uses 3-tier architecture(BLL, DAL and Presentation layers) and created 2 areas for account and admin. So here i dont know where to place my membership provider which are then accessed with every part of application for using Authorize Attribute.
I am overriding this method CreateUserAndAccount, Do i need to implement my own logic for saving user registration datas to database. But i find only some parameters are passed, how to pass my remaining custom fields from view to the controller using the dictionary object ?
public override string CreateUserAndAccount(string userName, string password, bool requireConfirmation, IDictionary<string, object> values)
{
throw new NotImplementedException();
}

As for question #2: Check out this question I asked this weekend... SimpleMemership CreateUserAndAccount Customization - specifically the blog post I linked in the question as it's very helpful about extending SimpleMembership.

For #1: Use DI to inject ExtendedMembershipProvider into your BLL layer as required. Map it in your DI configuration to Membership.Provider. This is effectively a DAL and should not contain business logic. Better still create a facade around WebSecurity and inject that into your BLL instead.
For #2: Yes the ExtendedMembershipProvider interface uses a dictionary of Key/Value pairs which can be used to map user profile properties to the database schema using an implementation of your choosing.
SimpleMembershipProvider does this by mapping the dictionary keys to corresponding database columns. Once the record has been created, you can then manage the user data using EF and the UserProfile model directly.
Implementing your own ExtendedMembershipProvider is a lot of work and I wouldn't recommend it. The SimpleMembershipProvider schema is relatively clean compared to legacy iterations, and I think you would need a very good reason for wanting to move password column to the user table, rather than just configuring SimpleMembershipProvider to use your own schema, and leaving password where it rightly belongs.

Related

Authentication and Authorization in Blazor WebAssembly with Database First Approach

Summary of my problem
My project is more complex but here is my problem at very basic level. I have a Blazor WebAssembly project where I do just basic CRUD operations.
I also have a small database and lets say I have two tables Users and Roles. What I do is to create their classes in Database-First fashion, by using Scaffold-DbContext and I run this command on the Shared project because I also want to reach to these classes from both Server and Client projects.
When I try to used Individual User Accounts on Authentication tab when creating a Blazor WebAssembly project, it creates the data models in the server. Which means I cannot access to my tables from Client Project. They need to be in Shared. Also it is Code-First based. I don't want to use migrations.
What I tried
What I tried to do is to create an identical -almost- project with Individual User Accounts projects but my Users class inherits IdentityUser and my DbContext inherits ApiAuthorizationDbContext but problem starts here.
I cannot add ApiAuthorization package from NuGet because it says Shared project does not compatible with .NetStandard 2.1.
Also changing Shared project's standard didn't work.
Some Questions
Can't I just add my users table on the Shared and use Identity from that table? (Since it's just a single table of rather larger database)
Do I need two databases for this? One for Identity, one for rest of the application?
Do I need to use Identity for Authentication & Authorization? What else can I use? Or Can I use a custom one where I can use it as I described earlier (Having models in Shared project)
My Goal
I want to authorize users with [Authorize] property. Since I cannot accomplish the registration, I cannot proceed.
Use 2 DbContexts. The Identity tables (yours or ASP.NET) should not be part of the Shared or Client projects.
I want to authorize users with [Authorize] property
The real authorization happens on the server, nothing in the client is safe. Have you looked at the complete (JWT based) implementation in the template?
Can't I just add my users table on the Shared and use Identity from that table? (Since it's just a single table of rather larger database)
No, Identity needs the base class. And your client app doesn't need (and shouldn't see) most of its properties.
Do I need two databases for this? One for Identity, one for rest of the application?
That is the best way. Note that you can have 2 DbContexts for 1 physical Db.
Link to the User wit a simple UserId (no Nav property) when needed.

How to manage multiple user types in IdentityServer4 using AspNet Identity?

What is the best way to store your user information per client? I have several applications which all use the same IdentityServer instance for authenticating. ASP.NET Identity shows how to extend a user by inheriting from IdentityUser.
public class CustomUser : IdentityUser
{
public Int32 CompanyId { get; set; }
}
However, I have applications that have mutually exclusive user information(eg. other applications don't need CompanyId and have properties the the CustomUser's application doesn't need.).
One way would just to create a single type containing all the properties for both. There could be a problem when a property overlaps where both applications need CompanyIds for different companies, not to mention that every column would always be queried every time a lookup was done, so this doesn't seem right. The other option is that I could just create a UserData table in the client applications and query from there as needed which is probably what I have to do since I don't think there is a better option.
If anyone knows a better way let me know.
If would be perfect if UserManager allowed for registration with multiple custom user types and you could get different subsets of data based your choice while each query was optimized for only the data it needed. Then you could put an SQL index per type and maybe even user TPH in entity framework to organize the information.
Unless diving too deep into too app-specific stuff, it looks like a normal user profile.It contains a number of claims describing the user. Let's consider only user specific, not application specific. For instance there are age, country, postal address, gender, whatever. And some apps need only age and country to restrict some content, while the others need postal address or email.Authorization request can contain a set of claims and scops to fulfill these requirements.All above is just about user information, not access rules, and all above is already in the protocol.
Regarding more app-specific... why not to store such stuff more close to the apps and link by user id...

ASP Net MVC Core - Load User Data From Active Directory when User browses Any Page

Here is my development environment:
Intranet Website
Active Directory Authentication/Authorization
Asp Net Core
I am trying to get the data stored in Active Directory attributes when a user enters firstly to any page in our application. All users rights and permissions, employeeid, studentid, etc.... are stored in AD Attributes and Security Groups. Some Attributes need to be displayed on the website too.
Let's say my website got the following urls...
http://mysite/Home/Index
http://mysite/Student/Index
http://mysite/Student/MyJobs
http://mysite/Staff/Applications
etc....
Any users can go onto some areas/urls of the website freely from other Intranet portals and I don't know where should I write the code to fulfill that criteria. The problem is that, there is no specific entry point to the application like http://mysite/Login or Authenticate, etc. If there is, I could load all users details and rights from AD on that single entry point.
In MVC5 era, I used Custom Global Authorize Attribute and put it on the BaseController is inherited from all other controllers to load that AD data. I put the AD's data into Session on the first hit and use the Static Class to display on Views and use in Controllers. But when I did some research in MVC Core, some say that it's outdated and I should use the Authorize Policy instead of custom Authorize Attributes.
Getting the data from Active Directory is already achieved by using my old webservices and we don't need to worry about .Net core not supporting AD yet.
I looked at the tutorials about Policy and saw something about Claims and Custom User Managers. I couldn't decide which one I should use to load data from Active Directory to the object (probably Scoped Object DI) which lasts for the whole user's session.
Should I load the data onto claims attributes
Eg...
var claims = new List<Claim>();
claims.Add(new Claim("UserName", "John.Smith", ClaimValueTypes.String, Issuer));
claims.Add(new Claim("RefNo", "02343001", ClaimValueTypes.String, Issuer));
claims.Add(new Claim("Email", "MyEmail#email.com", ClaimValueTypes.String, Issuer));
Or Should I write customized SignInManager and IdentityUser?
Eg...
public class ApplicationUser : IdentityUser
{
public string RefNo { get; set; }
public string Email { get; set; }
}
Is there anywhere I could put my code to check AD and load data?
And should I store the data in that Claimed Object rather than using Session Data?
Could you guys please advise me? Feel free to criticize if I miss anything and my idea is not working.
You're right in saying there's no System.DirectoryServices yet (it's on the backlog, I promise) so there are a couple of places to do this.
If you're already using Integrated Authentication you have SIDs for group membership, which are resolved when you call IsInRole(), so you can use role based membership (rather than Claims based) to solve basic authentication problems.
However if you want to support a forms based mechanism then you should look at using the cookie middleware, raw, to at least give you a simple login, calling your web service to validate your login. You could query your API in the controller code, and write an identity cookie. This cookie automatically encrypted and signed, so it can't be tampered with.
The problem comes when you want roles, and attributes. If you head down the cookie route you might be tempted to put all of those as claims in the identity before writing the identity out as a cookie. This might work, provided there are not too many - cookies have a maximum size (browser dependent, but under 4k usually). You can used chunked cookies, but there's a performance impact here. Instead you might use a reference cookie, where you put in a reference to another store where the actual fully populated identity is stored, be it session, redis or something else.
Then in the claims transformation middleware you can pull the reference out, go to your store, and rehydrate the identity.
I'd honestly avoid trying to merge all of this into ASP.NET Identity. That's mean to be the sole source for user information in an application, and in your case that's not true. Your sole source should be AD.
There's also a port of Novell's ldap library to core, which should stand in nicely for DirectoryServices should you want to avoid your web services approach.

What sort of membership system should I use?

[Problem]
I have a pre-built database with user credentials. The only thing I can change about this database is how the passwords are hashed. (Don't ask about that...let's just say it's dumb and I'm fixing it, please.) It's populated with credentials, so whatever I use has to mold to it. We are switching to the ASP.net MVC4 framework, and starting from scratch.
[Question]
What membership system should I use for the problem, if any?
It should:
a) allow me to check against the database using SHA512 for the password
b) set roles depending on the results
c) decorate the actions in the controller so I can feel like a boss
[Details]
Assume I've had a website for people who love to roleplay as toothbrushes. There's -a lot- (for a small- to mid-range website) of data already in the existing database. I'm moving to a brand new database layout and will be converting from the old one. We could change how the user system is managed, but to be honest we'd rather not do so. We have a user table with username and password. Very simple.
I have googled, and googled, and Stack Overflow'd, and Stack Overflow'd. What I have found is essentially a choose-your-own-adventure book where they either have blank page numbers, or the give me a page to an older book whose adventure isn't quite like this one.
I'm hoping that either a) someone will call me a dumb butt and point out I'm asking a duplicate question that leads to a resource with some complete example and/or documentation on how to do what I want or b) help me find a way.
As of right now I'm contemplating writing my own user management/authentication filtering system. I was going to go with the MembershipProvider but that seemed like overkill and didn't appear to do what I wanted it to. Maybe I'm narrowing my vision down too much.
I'm more than willing to hack my own way through and work to solve a problem, but I don't want to roll my own thing if there is something available that I can hook in to.
Update 1
Win made a comment about the MembershipProvider being independent of the MVC system which gave me an "Aha!" moment as things come together. I'm re-evaluating my research to see if I simply didn't put the puzzle pieces together correctly.
Update 2
After much help from dkroy and Win, I got a bit deeper into what is going on here. Once I have everything done I will include it in an edit for anyone else looking for information. Essentially, I was on the right track before I was thinking about scrapping it. I hadn't implemented a GetUser call, and I wasn't calling SetAuthCookie, so it wasn't working correctly. I'm now in the process of writing a RoleProvider.
a) allow me to check against the database using SHA512 for the password
Membership provider support SHA512.
b) set roles depending on the results
c) decorate the actions in the controller so I can feel like a boss
If you want to restrict user by role, you want to implement both Custom Memebership Provider and Custom Role Provider.
However, you do not need to override all. Here are the main ones -
// Membership provider
public override bool ValidateUser(string username, string password)
public override MembershipUser GetUser(string username, bool userIsOnline)
public override string GetUserNameByEmail(string email)
// Role provider
public override bool IsUserInRole(string username, string roleName)
public override string[] GetRolesForUser(string username)
You can Create your own custom RoleProvider and MembershipProvider. That way you will be able to use your existing database structures, and still leverage the MembershipProvider and RoleProvider contracts that ASP.NET implements to provide membership services. Minimal searching on custom MembershipProviders should get you started.

MVC 4 : Passing around user group data

I am in the process of rewriting my PHP website in ASP.NET and writing the membership system.
I understand I can extend MembershipUser to add member specific properties but how can I pass around boolean group information such as Use Search, Edit Posts etc which are not user specific? Is there a framework item I am missing or should I just create a super object to pass this and other settings around?
Essentially what I want it an efficient way to access the users group properties in my controllers.
Apart from extending the MembershipProvider, you can also extend RoleProvider. RoleProvider is in charge of checking to which group a user belongs to, registering new roles, adding user to role(s), etc. To work with roles you will use Roles class which contains a lot of static methods.
In addition to this, each time you hit a Controller, you can query HttpContext.User property which implements IPrincipal. This property has method IsInRole that is used to communicate with RoleProvider to obtain information if a user is in specific group or not.
Also, in order to allow access to controllers or actions you can use Authorization attribute and list specific roles that have access to the controller.
The roles can be stored in a cookie (to cache them) or you can implement Application_AuthenticateRequest in global.asax and initialize GenericPrincipal manually. This object is passed over to HttpContext.User. The constructor of this object accepts an array of roles that are queried with IsInRole method.
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
// Check if user is authenticated
if (HttpContext.User != null)
{
// Extract roles from a cookie if you used FormsAuthentication
// or read them from a cookie or from some other cached location
// Split roles into array of strings
var roles = listOfRoles.ToArray(); // If it is stored in a List<string>.
var identity = HttpContext.User.Identity;
var principal = new GenericPrincipal(identity, roles);
HttpContext.User = principal;
}
}
The above code is not tested. I wrote it from top of my mind. It should give you a pretty good picture how to cache roles and to use them in the most efficient way.
UPDATE: In case that you need more advanced options where each role can have one or more functionality like your "Use search", "Can do something", "Can do that", I would implement the following security logic:
Users
Roles (users belong to roles)
AccessRight (Role can have one or more access right).
UsersRoles table would be for adding users to specific roles.
RolesAccessRights table is where you define specific rights to each role.
User never talks to Functionality. (BTW, this naming convention is just an example, you will follow your naming conventions).
At my last work this is how we implemented the Audit system (it was Web Forms based). However, in MVC you could override AuthorizationAttribute to check user's role and to check if Role has defined access rights. Considering that you have specific security requirement, you would have to use this attribute on every action where you see the need and necessity.
If you plan to implement this logic, forget about Membership, MembershipUser and Roles. Honestly, I don't use these classes any more. I have my own custom security that I implement and which I used in the last 4 projects without any need for update or modification.
UPDATE 2: The security solution that we used was based on custom MembershipProvider and RoleProvider. Thinking about it now, it was a mistake to rely on that because access to AccessLevel table had to be mapped via Entity Framework. Therefore we had to ways to query our security tables.
My suggestion to you would be to ignore Membership- and Role-related classes completely. The first reason is that you would avoid bothering yourself with unnecessary methods and properties when you override the providers. There would be too many methods with throw new NotSupportedException() in the method body.
Suggested implementation
You will need the following tables:
Users - (You need at least three columns UserId, UserName, Password). If you want to hash the password, you might have to store salt as well. Other columns like FirstName, LastName, etc. I would suggest you to store in a different table and link it with UserId. As for UserId type it's up to you whether you would use int or Guid.
Roles - (You need at least two columns RoleId, RoleName). Again, as with UserId, it is up to you which data type you want to use.
UsersRoles - Store UserId and RoleId. You might want to store properties such as whether the role IsActive which is a bit value.
AccessRights - This is where you would store a key of your access right. In your case that is like UseSearch, EditPosts, DeletePosts, etc. Here you should use at least three columns AccessRightId, AccessRightKey and AccessRightDescription. This description field will turn to be pretty valuable if you have a lot of access right keys.
RolesAccessRights - This is where you define to which role you have added specific access rights. Also have IsActive bit value in order to disable the specific access right to a role.
In MVC you would override AuthorizationAttribute. In this attribute you would specify a list of access rights that have access to controller and/or actions. How you plan to do this is entirely up to you, but I would create an enum with a list of values that are the same as AccessRightsKeys. That way you can use strongly typed access rights instead of string based list. For more information about implementing custom authorization attribute have a look at the references list.
Inside of this attribute, you would read User ID and retrieve the roles. Compare the AccessRightsKeys that you specified against the roles (RolesAccessRights table) to see if the role has access right and whether the rule is active.
As for the solution based implementation I would implement Security service layer which communicates with Security-based repository and unit of work solutions. Because you are using MySQL I don't know which ORM you can use or would you have to rely on ADO.NET with OLEDB providers for MySQL.
My usual approach is a top-down approach. I implement from the high up (like Presentation layer) and go down towards data access layer. That way at the end I have only those methods which I really use and there is no redundancy.
Well, I hope this gives you some picture on how to this. As for time it takes, you can do this in about 8-10 hours.
Reference:
Implementing a Role Provider
Roles Class
How to: Create a Custom AuthorizationAttribute