SignInManager,what it is and how,when to use?

Alex picture Alex · Jul 19, 2016 · Viewed 33.4k times · Source

I am exploring SignInManager class. But the information given on MSDN is very useless. It only tells what are the methods and properties provided.

What I am looking for is,

1) What is SignInManager? 2) How to use it? 3) And I have my own database that contains credentials related info(username and passwords)

How can I use SignInmanager and how to use it so my custom database is used for authenticating users?

I am using asp.net MVC 5 and Visual Studio 2015. In my sample project I have accounts controller that contains action methods like

  public async Task<ActionResult> ExternalLoginCallback(string returnUrl)

But I have no idea how to use it, MSDN is completely useless to provide info on this. Any helpful links that explains it in details because I have no idea what SignInManager is and what it's for.

Thanks

Answer

n0rd picture n0rd · Jul 23, 2016

Disclaimer: I am confused by model used in ASP.NET identity myself and what I say is my understanding of things, that may be inaccurate (I might also be stating obvious things, so I apologize). Also, I was playing with Asp.Net Core's identity recently which is slightly different compared to what was available for Asp.Net 4, so I may mix things up.

Cookies

ASP.NET identity operates with two kinds of cookies: Application cookie and External cookie. Application cookie contains your application's identity and is issued by sign in manager. External cookie contains external authentication provider identity and is issued by authentication middleware (such as FacebookAuthenticationMiddleware, for example). You use sign in manager to consume the external cookie and issue application cookie instead. If you don't use external authentication you don't deal with external cookies.

Sign in manager

Class declared like this:

public class SignInManager<TUser, TKey> : IDisposable 
    where TUser : class, IUser<TKey> 
    where TKey : IEquatable<TKey>

So you may use any class as your user as long as it implements IUser<TKey> interface. Or use IdentityUser as your base if you start from scratch, which implements IUser<string>. In the past I attempted to create an implementation that uses int as TKey, but abandoned attempt after spending quite some time trying to make it work and not seeing any progress.

Password sign in

SignInManager.SignInAsync method issues application cookie for the specified user right away without any checks, so if you implement any custom authentication logic, you might want to use it (default asp.net MVC template uses it after registering user so they don't have to authenticate right after registration).

SignInManager.PasswordSignInAsync given the user name and password checks their validity and issues application cookie if they are correct.

External sign in

Instead of having the user to create login and password for your site specifically you might want them to use some external web site to authenticate and pass the authentication information to you with OAuth.

Asp.Net Identity has notion of User and Login, where User is... well, user (a person), and Login is the credential with which User authenticates. User might have multiple Logins.

OAuth flow as seen from Asp.Net web site looks like this (based on the default log in flow generated by VS template):

  1. You set up external authentication providers (authentication middleware) which you are willing to accept (that likely involves registering on external web site. For example, in order to use Facebook authentication you need to create Facebook app, set up return URL there to point to your web site and configure FacebookAuthenticationMiddleware with app ID and app secret Facebook provides you with).
  2. You present unauthenticated user with a choice of external providers you support.
  3. User picks a provider, the choice is sent to your Asp.Net web application
  4. Web application issues a ChallengeResult containing the name of the provider to be used (this usually happens in AccountController.ExternalLogin), return URL is set to call AccountController.ExternalLoginCallback and actual return URL user should end up in is saved for later.
  5. Appropriate middleware catches the ChallengeResult object and converts it into HTTP redirect response that causes user's browser to go to third party web site that asks user for credentials.
  6. Third part web site upon successful authentication redirects user back to you web site to the specific URL crafted by the authentication middleware (for Facebook it's /signin-facebook IIRC).
  7. Authentication middleware intercepts this call, validates the data passed by third party web site and if everything OK issues the external cookie, and redirects you to whatever was set as return URL at step 4 (which should be AccountController.ExternalLoginCallback).
  8. In AccountController.ExternalLoginCallback you are expected to consume the external cookie and issue an application cookie instead. That's what SignInManager.ExternalSignInAsync does: given the log in information it tries to find user with that Login. If it finds, it issues Application cookie; if it does not, it informs you and you should do what you think is right when you receive unknown Login (generally, you create new user at this point. Default implementation from VS template asks for additional info at this point and creates user in AccountController.ExternalLoginConfirmation). After that user is redirected to actual return URL "saved for later" in step 4.

Custom storage

I've been unsuccessful so far with creating custom storage for Asp.Net Identity. It generally involves implementing your own user manager class descending the UserManager<TUser, TKey> and storage class implementing bunch of interfaces like IUserStore<TUser, TKey>, IUserRoleStore<TUser, TKey>, etc.