I was trying to learn Asp.Net Identity and
in this tutorial,
Create an Entity Framework Code First ToDo model in Models\AppModels,cs part MyUser class
inherits from IdentityUser class and MyDbContext inherits from IdentityDbContext<MyUser> class. Why is that?
Lets say I have a User class that holds all the information of the user of my web application, should that class inherit from IdentityUser, and should my DbContext inherit from IdentityDbContext<User>?
Also, what are the advantages of inheritng dbcontext class from IdentityDbContext<TClass> over plain DbContext class as done in MVC 4
ASP.Net MVC 5.0 uses OWIN implemenation for plug and play.
There are couple of interfaces designed for this
FROM Scott Allen Article
IUser
A user object must implement the IUser interface, which requires every
user to have at least an ID and a name. The most notable aspect of
IUser is the Id property of type string. Strings work well for GUIDs
but can be a bit tricky when using integers for keys as is common with
SQL Server. More details in a future post.
IUserStore
The I*Store interfaces in the Core Identity assembly are factored to offer various levels of functionality.
IUserStore defines the bare minimum functionality you’d want for users
– create, retrieve, update, and delete (CRUD) functionality. If your
website wants to allow users to create local accounts with passwords,
you’ll want a component implementing IUserPasswordStore (which is an
IUserStore). For third party logins (Twitter and Facebook, for
example), add in IUserLoginStore, and for claim storage there is an
IUserClaimStore. Also, not shown in the class diagram above, is a
collection of interfaces for roles (IRole, IUserRoleStore, etc). Let
the debate on roles versus claims begin.
UserManager
The UserManager is a concrete class and it is the UserManager that provides the domain logic for working with user information. The UserManager knows when to hash a password, when to validate a user, and how to manage claims.
There are a few extensibility points with the UserManager, for example, the manager has a number of properties you can use to set a custom user validator (any object implementing IIdentityValidator), a custom password validator, and a custom password hasher. The primary extensibility point is via the UserManager constructor, which allows you to pass in any object implementing IUserStore. If you want to use a UserManager to manage user information stored in SQL Server, we’ll look at pre-built classes to do this in a later post, but it is also easy to create an IUserStore to work with a document database or other forms of storage.
Remember an IUserStore doesn’t know how how to work with user passwords, only an IUserPasswordStore knows about passwords. The UserManager is aware of the different core interfaces and will try to work with the capabilities of the store object given in the constructor. For example, if you use FindByIdAsync the UserManager can use the user store to query for a user by ID, but if you invoke FindAsync (which takes a username and a password), and the underlying store doesn’t implement the IUserPassword store interface, the UserManager will be forced to throw an exception.
It’s tricky to use a single concrete class for everything from users to passwords to claims, and tradeoffs must be made. We’ll also look at some of the tradeoffs in upcoming posts.
EDIT: Check out Implementing ASP.Net Identity
Now ASP.Net identity supports generic IdentityUser<TKey> before it was a string,i.e UserId was a string
The IdentityDbContext<> class is a class that inherits from DbContext as you would usually do but provides ready DbSets for Roles and Users.
See class doc here:
http://msdn.microsoft.com/en-us/library/microsoft.aspnet.identity.entityframework.identitydbcontext%28v=vs.111%29.aspx
Yes, your user dto should inherit from IdentityUser and any additional fields you want in your database associated with your user can be added to that class.
This makes it much easier to add additional fields to your database that are associated with your user and if you are using Entity Framework migrations and database initializes it means that you can now generate the entire Identity database from your DbContext.
Related
It seems that all the recommended approaches I see on the internet are to use the UserManager<TUser>.CreateAsync() method to create users.
What are the downside of using only ef core dbContext?
Say that I have a TimeZoneInfoId column in AspNetUsers.
public class ApplicationUser : IdentityUser
{
public string? TimeZoneInfoId { get; set; }
}
Is it bad to update it using dbContext?
For instance:
using var dbContext = await DbContextFactory.CreateDbContextAsync();
var userToUpdate = await dbContext.ApplicationUsers.Where(u => u.UserName == "John").FirstOrDefaultAsync();
userToUpdate?.TimeZoneInfoId = "Samoa Standard Time";
await dbContext.SaveChangesAsync();
Or is it perfectly fine to do so?
First of all, UserManger is another level of abstraction. Usually it's used with EF-based user store, but you may implement ANY store you want.
So if you use UseManager project-wide and at some development stage you decide that you want to switch current EF-based user store to something else, the only thing to do is to replace IUserStore in your UserManager. If you go the way you provided (calling db directly) - you'll be supposed to refactor EVERY place where you managed the user.
User manager takes care about few more things, for example: updating security stamps / normalization or validation - it's very important to know, that you can modify every aspect of UserManager - the only thing you have to do is to switch UserManager abstraction to another one - just like in case of IUserStore.
To sum up, UserManager work's like a good glue for many components which allows you to manage users. In default it uses good default implementations but it's very easy to adjust it any way you need.
Here is an explain about why we choose to use UserManager and RoleManager.
ASP.NET Core Identity:
Is an API that supports user interface (UI) login functionality.
Manages users, passwords, profile data, roles, claims, tokens, email
confirmation, and more.
It's not just database access. It is also code that manages login functionality, secure token creation, secure password management and much more.
You need to take all of the above into consideration if you create a custom system, have an external auditor to pen-test your solution (even though this is a good idea whatever choice you make), unit test, performance test etc.
All the above is already done. You can easily customize the identity with various hook points too.
BTW, identity uses ef to access the datastore already by default.
Do structure your multilayer application, but leave identity out of it. It is a horizontal concern and it's presence is there to simplify your development and let you worry about your business needs only.
It's very difficlut to define bad in your code, But userManager provides developers with a more convenient, efficient and safe choice.
refer to link
EDIT: I should probably add that in my project (which was based on the ASP.NET Core 2.1 - WebApp with MVC, with "Individual User Accounts), I don't have "AppUser" (or an equivalent class that inherits from IdentityUser), and ApplicationDbContext inherits from IdentityDbContext - not from IdentityDbContext (or IdentityDbContext).
I'm currently learning / starting with ASP.NET Core and use "Add New Scaffolding Item" to Add Custom user data to Identity and noticed that I cannot use the existing context (ApplicationDbContext) if I want the scaffolder to create my custom user class. The only way to have that field enabled is if I add a new context, which will also add a new connection string. But the new context seems to be essentially doing the same that my already existing context does.
I also noticed that the two new classes (AppExtendedContext and AppExtendedUser in my case) were put under Areas/Identity/Data, while I'd actually expect them to be under Data and Models.
So I was wondering: Why? ;-)
Or, to put it in more actionable terms: Would it be safe to refactor the generated code back to only use a single ApplicationDbContext? What would I be losing / what kind of trouble would I get myself into?
The answer could be as simple as "for pragmatic reasons" (e.g. because it makes the automatic code generation easier / safer); and in that case, moving these things around should be fairly safe as long as I'm not going to use the scaffolder again. But then again, it might make life more difficult/confusing when upgrading (e.g. to ASP.NET Core 2.2, or ASP.NET Core 3.0).
Just trash your AppExtendedContext and AppExtendedUser classes and use the ApplicationDbContext and AppUser and add your customizations there.
They are ready for modification (they inherit from IdentityDbContext<TUser> and IdentityUser<TKey> respectively. Feel free to rename them to something more familiar to your application (such as Customer or CustomerUser), if you don't like the AppUser name.
There's really no need to inherit from AppUser or ApplicationDbContext, they are the final/concrete classes for your Core Identity.
Make sure your context inherits from IdentityDbContext<>. You have to specify the type to use for your application user, which you can just create as a class that extends IdentityUser (given the fact you want to start extending the IdentityUser class). Go for something like YourCustomContextType : IdentityDbContext<YourCustomUserType>.
As for the Identity services registration you need to specify your class there too using AddDefaultIdentity<YourCustomUserType>().AddEntityFrameworkStores<YourCustomContextType>().
Make sure you also look at how other people approach extending the Identity functionality:
How to extend available properties of User.Identity
I´ve started development on a new ASP.NET MVC-App and I want to use ASP.NET Identity 2 for user-management. I want to get rid of the role-thing because I think this is absolutely not needed, especially if I think of the way, ASP.NET Identity handle roles behind the scenes: As claims. (please correct me if I´m wrong here)
I have two information regarding this issue: This official Microsoft-Documentation points out, that one only needs to implement the features needed, if the out-of-the-box-approach not meet all requirements. The other information is, that one have to derive the custom User from Microsoft.AspNet.Identity.EntityFramework.IdentityUser. But IdentityUser implements IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>, IUser, IUser<string>
From my perspective, these information are not really compatible, because if I derive from this IdentityUser, I will take all this stuff into my CustomUser-Implementation whether I need it or not.
There is one more thing I wonder about: As I understood the Identity-Architecture, there are mainly two segments: Stores and Managers. The Manager is coupled to the Application and the Store, while the Store is coupled to the Manager and the Storage.
The storage-Interfaces are as flexible as I expected. Maybe I should start here - but I still don´t know, how to create a customUser as an entity, which derives from IdentityUser, without any reference to Roles. Can anyone tell me what my problem is?
The only stackoverflow question I found regarding this issue is
here. But I won´t believe, that this is an approach to follow.
Well, first and foremost, you can't truly get rid of roles. You can choose not to use them, but you're still going to have an AspNetRoles table. There is no way to get rid of that as the role functionality is baked in. Identity is extensible in that you customize and extend the role, but the relationship is not removable. The Microsoft documentation is not wrong, here, per se; it's just perhaps not entirely clear. You don't have to implement any role-based functionality if you don't want to use roles. In other words, you don't have to create functionality to manage roles, assign roles to users, or to verify that users are in particular roles. However, that doesn't mean that the core role functionality ceases to be present in Identity: only that you may simply choose not to use it.
Second, roles are actually kind of needed, at least if you have any desire to have permission-based access controls. If every logged in user can do everything any other logged in user can, then roles are probably not necessary, but if there's any functionality that's specific to a subset of users, then you need roles. Also, roles are not claims, though they function much as claims do. Identity has a separate concept of "claims", though.
In ASP.NET MVC, you get the default AspNetUsers table that stores all user data.
Now in most projects, you want to refer to the user that created, for example, a post. You also want to keep your database logic separate from your web logic, so you most likely put database logic in a class library.
But then, you encounter some issues: How do I refer to a AspNetUser? Should I move the ApplicationUser to the class Library? Should I even add foreign keys to this table?
I've seen many questions and answers about how to add a foreign key to AspNetUser table and how to move the ApplicationUser part to the Class Library, but I have my doubts in terms of security for the following things:
Part of the database is going to be exposed through an API, mostly for AngularJS Client-Side calls, but later perhaps for third-party websites. Having a foreign key to the UserId in the a table will expose the UserId on a GET call, which I've been told that this should be kept secure... right?
Isn't the default security logic template created in such a way that modifying it should be avoided? (Moving ApplicationUser to class Library).
To get the logged in user you have to use System.Web.HttpContext.Current.User.Identity.GetUserId();, which I'm not sure about how secure this is in a class library and if this is any good as it uses System.Web, is it common to use this in a class library that should only handle database logic?
It still requires an correct connection string in web.config, so the database handling still isn't really separated from the MVC application.
Calling the database correctly for userId should be avoided according to this answer.
So let's just say this is not a good way of creating your project, what are my alternatives? How would I correctly refer to an user?
In another project I used a third table, which contains additional information about the user, where one string is the e-mail address. This e-mail address is sequel (and unique) to the logged in Username (User.Identity.Name). This third table is only exposed through the API in such a way that it hides the e-mail address. It still requires System.Web.HttpContext.Current.User.Identity.Name; though.
My question to you guys is, What is best practice in 2015?
Well, that is an interesting question. The following answers are based in my opinion.
How do I refer to a AspNetUser? Should I move the ApplicationUser to
the class Library?
In that case, you should have the ApplicationUser class as part of the Class Library Project (usually called Infrastructure). Once you are using EF, you must have all the classes to control its relationships.
Answering the question: Yes, you should!
Should I even add foreign keys to this table?
Yes, you should! That's why the class is there, to be modified as you need. Typically, the other classes has FKs that references the ASP.NET user.
Part of the database is going to be exposed through an API, mostly for
AngularJS Client-Side calls, but later perhaps for third-party
websites. Having a foreign key to the UserId in the a table will
expose the UserId on a GET call, which I've been told that this should
be kept secure... right?
Yes. HOWEVER, you should never return your entity from an API. You MUST create a Class (or Anonymous Class) that only contains the properties you want to show. For example, instead of returning the entire User object, use LINQ Select method to select only the safe properties.
Isn't the default security logic template created in such a way that
modifying it should be avoided? (Moving ApplicationUser to class
Library).
No! The class is there because you may need to modify it (you can add new properties or use it in relationships), and it will not affect the security logic.
To get the logged in user you have to use
System.Web.HttpContext.Current.User.Identity.GetUserId();, which I'm
not sure about how secure this is in a class library and if this is
any good as it uses System.Web, is it common to use this in a class
library that should only handle database logic?
This thread may answer your question User.Identity.Name - which assembly reference brings that into your project?. In other situations you pass all the necessary parameters from the asp.net project.
It still requires an correct connection string in web.config, so the
database handling still isn't really separated from the MVC
application.
Yes, it still requires a connection strings in web.config. It happens because the connection string depends on the starter project. You may have several asp.net projects, that has the same infrastructure, but different databases.
Calling the database correctly for userId should be avoided according
to this answer.
Yes, it should! Because (in that case) the UserManager class already has methods that handles the User entity. For example: UserManager.FindById()
In another project I used a third table, which contains additional
information about the user, where one string is the e-mail address.
This e-mail address is sequel (and unique) to the logged in Username
(User.Identity.Name). This third table is only exposed through the API
in such a way that it hides the e-mail address. It still requires
System.Web.HttpContext.Current.User.Identity.Name; though.
You can add a string property in the user class to hold this information. In your login logic add a new Claim (called email in that case) to the current user. Then, you will be able to access the email of the current user without querying the database. Take a look at this link How to add claims in ASP.NET Identity
Hope it helps!
Why is the IdentityUser class in the Microsoft.AspNet.Identity.EntityFramework package instead of being included in the Microsoft.AspNet.Identity.Core package?
Why should it depend on EntityFramework? It seems to be a simple class.
What am I missing?
I typically separate by Data layer from my DAL. Adding a dependency to EntityFramework for the IdentityUser class seems a bit much.
The design of the core of Identity is not coupled to EF or to any specific shape of user and role types. Everything is abstracted by the stores. In fact, for any given persistence provider, the types don't even need to be POCOs at all!
For Identity 3.0 we considered having our current types in core (in fact, at some point we had them there) but we got pretty solid feedback from people familiar with other persistence frameworks that although those types can comply to a common definition of "POCO", they are very EF specific.
We also considered having base classes in core that we would extend for EF in the EF package. We landed where we are because there didn't seem to be enough benefit in this. It was between adding the complexity of an extra layer of inheritance (more complexity would make it easier for us to introduce bugs) vs. the fact that the types themselves aren't that complex and that persistence provider writers who want to take them as a starting point are welcome to copy & paste the code.
You asked:
Why is the IdentityUser class in the
Microsoft.AspNet.Identity.EntityFramework package...Why should it
depend on EntityFramework?
This is because the out-of-the-box implementation for Identity actually depends on Entity Framework.
The ASP.NET site has the following article:
Overview of Custom Storage Providers for ASP.NET Identity which indicates:
By default, the ASP.NET Identity system stores user information in a
SQL Server database, and uses Entity Framework Code First to create
the database. For many applications, this approach works well.
However, you may prefer to use a different type of persistence
mechanism, such as Azure Table Storage, or you may already have
database tables with a very different structure than the default
implementation. In either case, you can write a customized provider
for your storage mechanism and plug that provider into your
application.
The same page also should answer your question in the comments about creating a custom implementation of IUser:
Customize the user class
When implementing your own storage provider, you must create a user
class which is equivalent to the IdentityUser class in the
Microsoft.ASP.NET.Identity.EntityFramework namespace: