I am using the ASP membership services to create and manage users. I notice that on user account registration everything works fine... Until I call Roles.AddUserToRole, and suddenly I get a second user account created in the aspnet_users table. Can someone explain this? I am quite certain that I should only ever have one user account in the database per registered user...
Roles and membership are separate concerns, e.g. do not depend on one another, so the multiple records in aspnet_Users do indicate that you may want to examine your configuration and ensure that your membership and roleManager elements either:
both have NO applicationName defined (default '/') or
both have the SAME applicationName defined
http://weblogs.asp.net/gurusarkar/archive/2010/01/09/asp-net-mebership-creates-two-users-in-aspnet-users-table.aspx
Related
Having trouble finding a good lead on this. I have a aspnetcore app with identityserver4 configured to use asp identity with a sql database.
There is a business requirement that all non AD users are stored in this asp identity database.
All AD users are defined on Azure. I can authenticate them with LDAP and receive their data.
The issue comes after authentication. Whenever asp identity tries to call:
var user = await UserManager.FindByNameAsync(userName);
With an AD user, it fails because the user does not exist. This is because it is using EF to query the asp identity database, where those users are not defined.
private DbSet<TUser> UsersSet { get { return Context.Set<TUser>(); } }
I can not store any of the AD information in the asp identity database (business requirement). I am trying to find a way to get the user store to look both at the asp identity tables, as well as Azure (via LDAP).
My current method for getting the AD users when doing initial auth is here:
await GetADUser(queryParams),
It uses LDAP to authenticate and grab the user object.
One additional requirement is that I can not use an external login screen, the login must all be done from the same company facing login UI. AKA no external providers.
As per #mxmissile, abstracting the UserManager out was the correct call. Then you can also abstract out other managers as needed for special functionality. This is in fact the only class in the inheritance layer for this part of the code that is virtual.
There are built in functions that let you register your custom managers:
services.AddIdentity<IdentityUser, IdentityRole>()
.AddUserManager<ApplicationUserManager<IdentityUser>>()
.AddSignInManager<ApplicationSignInManager<IdentityUser>>()
Hopefully this is a little help to any others that have a similar question. I ended up just overriding a couple of the functions from the base user manager and just calling the base method for anything that did not need my new logic. By default it looks like ASP Identity does not try to look up users by email - just fyi.
Im using asp.net identity and I have a number of user classes that inherit from IdentityUser.
Lets say I have an inheritance chain like:
IdentityUser <- AppUser <- ServiceUser <- ServiceEmployee and ServiceCustomer (which both inherit from ServiceUser).
When trying to create a unified login form whats the best strategy?
If you use the OTB account controller and change the UserManager to use ServiceUser but try to login an account that was registered as ServiceEmployee it will fail because FindAsync() apparently only tries to find based on "ServiceEmployee" in the discriminator field, so if the account was registered as a different "type" it cant be used to login. So this happens with any combination when registered vs login types differ.
Should I update the login action to use multiple UserManagers so that there is a check against each user type or is there some better way to do what I am trying to achieve.
Thanks for any info.
Have you considered keeping your identity users and your own application users separate? Meaning User is what holds your identity information and Person is what the rest of your application uses (and other types such as Employee inherit from). This is how I do it myself. I keep all security/identity stuff completely separate (in separate project/context) and only link my User and Person entities which works great for me - much easier to maintain and update my security model without affecting the rest of my application and (as much).
When you create a new ASP.NET internet application, you get the built in membership tables and controllers etc. There are 5 tables created:
UserProfile
webpages_Membership
webpages_OAuthMembership
webpages_Roles
webpages_UsersInRoles
I understand the basic concept of how all these work but I have a question on why is a UserProfile create along with the webpages_Membership? Can't these 2 tables practically be combined together? If that's not how it works, can you explain to me why the 2 files were created.
No, they cannot be combined, because a user profile has nothing to do with membership. Membership is about your user id, password, and authentication. User Profile is about things like name, address, etc..
It's designed this way so that you can extend the user profile to include whatever information you want. While the Membership tables do not change, because those are "hard wired" into the provider.
This is a weird way to state the question, but this is what I'm trying to achieve.
This is what I'm doing
Connect to a MySQL Db(complete)
authenticate(complete)
select all the roles that I have specified in mySQL (complete)
store those roles somehow so I can display controls and links based on their role membership.
I just got this figured out to handle the mySQL part in web.config
system.web
membership defaultProvider="MySQLMembershipProvider" /
roleManager enabled="true" defaultProvider="MySQLRoleProvider" /
/system.web
I'm using this as code
MySqlDataReader dr2 = cmd2.ExecuteReader();
while (dr2.Read())
{
string roleName = dr2["role"].ToString();
//error here -> Roles.AddUserToRole(userID, roleName);
}
Access denied for user ''#'localhost' (using password: NO)
Is Roles.AddUserToRole really what i'm looking for to satisfy my needs. I think I need to store the user roles in the sessio don't I? I
Is Roles.AddUserToRole really what i'm looking for to satisfy my needs. I think I need to store the user roles in the sessio don't I?
NO! Adding user to roles means the provider will link the user to the role. As you already have the user linked, this is a worthless direction.
store those roles somehow so I can display controls and links based on their role membership
Why do you need to do this? At the page level, you can set up ASP.NET security with trimmings so you can automagically exclude pages from the user's view if they are not in the correct role(s). As far as sections/controls/etc, you can check to see if a user IS in a role and then determine whether or not to display it. If you use sections, a lot of this can be done declaratively rather than programmatically.
The one caveat is what your membership provider supports. The "out of the box" providers (Access and SQL Server) support security trimmings and declarative syntax for exclusions of sections of a page, etc. If the MySQL provider full implements all of the methods, you should be fine using it, as well. If you create a custom provider, there are certain parts YOU have to implement to get things to work.
The short story is once you grab a membershipUser (authenticate the person), you will have access to whether the person is in role or not. This is all part of the standard implementation of a membership provider in .NET. As long as the provider you are using for MySQL covers all of the same methods, you can do a quick google search and find tons of sites showing how to show/hide bits based on roles.
I know how to create users and assign them to roles etc, but when I tried to dig a bit deeper into how roles and membership tables are able to establish a relationship between each other, I got totally lost ( BTW – I do know how foreign/primary keys work ;) )
BTW - I've created tables in databases using aspnet_sqlreg wizard
Q1 - Both SqlRolesProvider and SqlMemebershipProvider have a property ApplicationName. I thought that in order for the two providers to be able to create association between their users and roles, they would both have to use same value for ApplicationName property. But that doesn’t seem to be the case.
A) Anyways, I assume that SqlRolesProvider.ApplicationName property is only used to distinguish between table entries belonging to different role providers, but they don’t use that property in order to associate their roles only with membership providers with the same ApplicationName value?!
B) But wouldn’t it be most practical if roles providers could only be associated with membership providers with the same ApplicationName value ( thus where SqlRolesProvider.ApplicationName == SqlMemebershipProvider.ApplicationName)?!
Q2 - I was also curios whether roles and users could be associated if roles provider was connected to DB1, while membership provider was connected to DB2. Somehow I was still able to assign users to different roles, even though roles were defined in different database.
A) But why is that? Namely, if SqlRolesProvider.ApplicationName = “rolesP” ( ApplicationID=10 ) and SqlMembershipProvider.ApplicationName = “membership” ( ApplicationID=100 ), then in order for the table in DB1 to have relationship with table in DB2, the two would have to reference each other via ApplicationName entry ( actually via ApplicationID), which would act as foreign/primary key.
But the thing is, none of the foreign key fields in DB1’s tables holds a value equal to SqlMembershipProvider.ApplicationID = 100, which would suggests that there is no relationship established between tables in DB1 and DB2 ( I know that is not the case, since I’m able to assign users to roles ). So what am I missing?
thanx
EDIT:
Uh, don't know if anybody will still be reading this, but I did some more digging and got even more confused:
If both roles (with applicationName=R1 and applicationID=10)and membership provider(with applicationName=M1 and with ApplicationID=100) are in same DB, then creating a new user causes aspnet_Users table two create two entries for same user name– one with ApplicationID=10 and other with ApplicationID=100. As far as I know, when new user is created, only one field ( with ApplicationID=100 )should be added to aspnet_Users. Uh?!
Have you looked at the aspnet_UsersInRoles Table. This is the table that links the user to the role. The RoleProvider is designed to be separate from the MembershipProvider so that you can have them in separate DB's. Additionally it allows for you to set up roles for one application name and re-use those roles in two separate applications that each have a different application name for the membership provider. Don't get stuck in the mentality that you have to have the same application name for both providers or that your application name needs to match the running application. You don't need to have any name at all if you don't want to. I hope that this helps.
I had a hard time following what you were saying...
Anyway... you seem to be looking at the database too much. Have you configured the web.config for your membership providers and were you able to query "Membership" using C# and NOT SQL queries?