I'm very new to Asp.Net Identity and please bear with me if this question seems silly. So, when I read the definition for UserStore class and UserManager class in Microsoft website which are in the links below, it looks like both class define operations around users (like Add, Find, Delete and Modify). So when do I use one over the other?:
https://msdn.microsoft.com/en-us/library/dn315446(v=vs.108).aspx
https://msdn.microsoft.com/en-us/library/dn613290(v=vs.108).aspx
Things are quite complicated there and could have been easier.
UserManger
is the ... manager. It does not really interact with the storage, the database.
That's what the UserStore
does.
In fact UserManager has a constructor which needs a UserStore.
Why would you have to different object to manage users?
Well, the main reason is you can decide not to use EF and create your own user store.
Things get clearer when you try to implement your own storage provider.
I did it and my code can be downloaded from github.
This is the UserManager. As you can see there's not much in there. Just a few lines of code to configure the validator.
UserStore on the contrary, is quite big. In that example I've implemented a few interfaces and overridden a few methods.
That's what you would do if you want to customize the interaction with the database and/or extend your classes.
You don't normally interact with the UserStore
and in fact it's hidden. You just create it and pass it to the UserManager
and ... forget about it.
You can always customize your UserManager and expose the UserStore:
public class UserManager : UserManager<User, int>
{
public UserManager(IUserStore<User, int> store): base(store)
{
this.Store = store;
}
public IUserStore<User, int> Store { get; set; }
}
and, maybe, ovveride some of the methods:
public class UserManager : UserManager<User, int>
{
public UserManager(IUserStore<User, int> store): base(store)
{
this.Store = store;
}
public IUserStore<User, int> Store { get; set; }
public override System.Threading.Tasks.Task<IdentityResult> CreateAsync(User user)
{
return base.CreateAsync(user);
}
}
but that would be pointless unless you have to do some peculiar customization.
Let's say you want to create a user using the store instead of the manager. You can do something like this:
await this.UserManager.Store.CreateAsync(new Custom.Identity.User() { UserName = "LeftyX" });
and it would work.
In the class above, as you can see, I've overridden the CreateAsync
in the UserManager.
That method calls UserStore.CreateAsync()
and in fact, you have to call the base method CreateAsync:
public override System.Threading.Tasks.Task<IdentityResult> CreateAsync(User user)
{
return base.CreateAsync(user);
}
If you don't do that and, for example, return null instead, the UserStore.CreateAsync
wouldn't be called and the user wouldn't be created.
It makes sense at the end.
I guess the best way to understand how this framework works is to try and customize/implement your solution with your own storage and see how all the classes interact with each other.
The sample project does not interact with a database but uses a json storage. It's very easy to debug. Give it a go and things will be clearer at some point.
Identity is based on two primary blocks in ASP.NET Identity. There is an authentication manager which takes on the form of the UserManager<T>
class. There is also the store manager which is an instance of UserStore<T>
.
Difference?
The UserStore<T>
object is injected into authentication manager which is used to identify and authenticate the UserStore<T>
identity. The UserManager<T>
reference acts as the authenticator for the UserStore<T>
identity.
Important Details
ASP.NET Identity is based on the newest Open Web Interface. This means that that [typically], the IAuthenticationManager interface as declared in Microsoft.Owin.Security
: Linked here, the authenticator injected into the UserManager
class and controller and basically every operation that involves an authentication step.
In the following:
private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
var identity = await UserManager.CreateIdentityAsync(user,
DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties() {
IsPersistent = isPersistent }, identity);
}
We can notice the UserManager
authentication manager being used to check the "UserStore
" application user against the identity of the authentication manager. Snippet taken from blog.
Conclusion
The UserManager
is the essentially the domain logic of your ASP.NET Identity. The controller you use to handle a "login" or "identification" is passed in by a UserStore
, which as MSDN: Userstore depicts...
Represents an Entity Framework implementation of a user store that supports IUserStore, IUserLoginStore, IUserClaimStore and IUserRoleStore.
Once the UserStore
has all necessary fields to be qualified as an identity and you have qualified the UserManager
as the authentication manager, and a method of storing the context...aka IdentityDbContext
or some other method of storing the values in SQL (If used), you will have a Identity system capable of supporting logins.
I was watching Identity tutorial on YouTube, and I think this screenshot might help:
So UserManager is the actual class that you should work with but it does not know how to store and retrieve data from database. it even does not know where the data is going to and coming from.
For those things it uses UserStore and says to it for example "Hey UserStore I have a new User that needs to be saved for future use, I don't know where you're going to save it and how you're going to do it, just save it for me"
Then the UserStore does the actual work such as where should the data be saved? which database? and how? the default one uses EF and SQL Server so if you want to use some other database for example MySQL you're going to need a different UserStore.
This is one of the features that were added to Identity compared to Membership that only worked with SQL Server.
The same concept is true for RoleManager and RoleStore.