Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom ASP.NET Identity 2.0 UserStore - Is implementing all interfaces required?

I've created a custom IUserStore<TUser,int> for my application. I've implemented the interfaces I need,

   IUserStore<TUser, int>,
   IUserRoleStore<TUser, int>,
   IUserLockoutStore<TUser, int>,
   IUserPasswordStore<TUser, int>

but when I call

var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);

I get an exception saying

Store does not implement IUserTwoFactorStore<TUser>.

I'm not using two factor authentication anywhere in my application. Why does it expect me to implement that interface? Is it required that I implement all of these interfaces, even if I don't actually use them?

like image 530
Stephen Collins Avatar asked Aug 28 '14 14:08

Stephen Collins


People also ask

What interface will you implement if you want to use your own database schema to store users but still use the basic functionality of ASP NET core?

The IUserStore<TUser> interface is the only interface you must implement in the user store.

What is Userstore?

A user store is the database where information about the users and user roles is stored, including log-in name, password, first name, last name, and e-mail address. The user stores of all WSO2 Carbon-based products are embedded H2 databases except for WSO2 Identity Server, which has an embedded LDAP as its user store.

What is IdentityResult?

IdentityResult(Boolean) Constructor that takes whether the result is successful. IdentityResult(IEnumerable<String>) Initializes a new instance of the IdentityResult class with the specified error messages.

What is identity in .NET core?

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.

What is new in ASP NET identity 2?

ASP.NET Identity 2.0: Customizing Users and Roles. The ASP.NET Identity team released the Identity 2.0 framework RTM back in march. The new release contained significant additions to the functionality found in the original 1.0 release, and introduced some breaking changes as well.

What is a custom storage provider for ASP NET identity?

ASP.NET Core Identity is an extensible system which enables you to create a custom storage provider and connect it to your app. This topic describes how to create a customized storage provider for ASP.NET Core Identity. It covers the important concepts for creating your own storage provider, but isn't a step-by-step walkthrough.

What are managers and stores in ASP NET identity?

Managers are high-level classes which an application developer uses to perform operations, such as creating a user, in the ASP.NET Identity system. Stores are lower-level classes that specify how entities, such as users and roles, are persisted.

What is ASP NET Core Identity?

ASP.NET Core Identity consists of classes called managers and stores. Managers are high-level classes which an app developer uses to perform operations, such as creating an Identity user. Stores are lower-level classes that specify how entities, such as users and roles, are persisted.


2 Answers

Actually the IUserTwoFactorStore interface is really simple, so far my implementation (I don't use two factor auth either) is this:

 ....
 public Task<bool> GetTwoFactorEnabledAsync(User user)
 {
     return Task.FromResult(false);
 }

 public Task SetTwoFactorEnabledAsync(User user, bool enabled)
 {
     throw new NotImplementedException();
 }

It works, although I just did it couple minutes ago and didn't test whole app thoroughly.

like image 83
Ignas Vyšnia Avatar answered Oct 28 '22 03:10

Ignas Vyšnia


I had the same problem. For the moment, as the SignInManager.SignInOrTwoFactor method blindly checks for the GetTwoFactorAuthentication it throws an exception when the UserStore doesn't implement the IUserTwoFactorStore.

I believe Microsoft intended that the SignInManager PasswordSignInAsync method must be overriden in a custom SignInManager class. Unfortunately I couldn't find any documentation or samples pointing so.

Here is the SignInManager wrapper class I implemented to solve this issue:

public class EnhancedSignInManager<TUser, TKey> : SignInManager<TUser, TKey>
    where TUser : class, IUser<TKey>
    where TKey : IEquatable<TKey>
{
    public EnhancedSignInManager(
        UserManager<TUser, TKey> userManager, 
        IAuthenticationManager authenticationManager)
        : base(userManager, authenticationManager)
    {
    }

    public override async Task SignInAsync(
        TUser user, 
        bool isPersistent, 
        bool rememberBrowser)
    {
        var userIdentity = await CreateUserIdentityAsync(user).WithCurrentCulture();

        // Clear any partial cookies from external or two factor partial sign ins
        AuthenticationManager.SignOut(
            DefaultAuthenticationTypes.ExternalCookie, 
            DefaultAuthenticationTypes.TwoFactorCookie);

        if (rememberBrowser)
        {
            var rememberBrowserIdentity = AuthenticationManager
                .CreateTwoFactorRememberBrowserIdentity(ConvertIdToString(user.Id));

            AuthenticationManager.SignIn(
                new AuthenticationProperties { IsPersistent = isPersistent }, 
                userIdentity, 
                rememberBrowserIdentity);
        }
        else
        {
            AuthenticationManager.SignIn(
                new AuthenticationProperties { IsPersistent = isPersistent }, 
                userIdentity);
        }
    }

    private async Task<SignInStatus> SignInOrTwoFactor(TUser user, bool isPersistent)
    {
        var id = Convert.ToString(user.Id);

        if (UserManager.SupportsUserTwoFactor 
            && await UserManager.GetTwoFactorEnabledAsync(user.Id)
                                .WithCurrentCulture()
            && (await UserManager.GetValidTwoFactorProvidersAsync(user.Id)
                                 .WithCurrentCulture()).Count > 0
                && !await AuthenticationManager.TwoFactorBrowserRememberedAsync(id)
                                               .WithCurrentCulture())
        {
            var identity = new ClaimsIdentity(
                DefaultAuthenticationTypes.TwoFactorCookie);

            identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, id));

            AuthenticationManager.SignIn(identity);

            return SignInStatus.RequiresVerification;
        }
        await SignInAsync(user, isPersistent, false).WithCurrentCulture();
        return SignInStatus.Success;
    }

    public override async Task<SignInStatus> PasswordSignInAsync(
        string userName, 
        string password, 
        bool isPersistent, 
        bool shouldLockout)
    {
        if (UserManager == null)
        {
            return SignInStatus.Failure;
        }

        var user = await UserManager.FindByNameAsync(userName).WithCurrentCulture();
        if (user == null)
        {
            return SignInStatus.Failure;
        }

        if (UserManager.SupportsUserLockout 
            && await UserManager.IsLockedOutAsync(user.Id).WithCurrentCulture())
        {
            return SignInStatus.LockedOut;
        }

        if (UserManager.SupportsUserPassword 
            && await UserManager.CheckPasswordAsync(user, password)
                                .WithCurrentCulture())
        {
            return await SignInOrTwoFactor(user, isPersistent).WithCurrentCulture();
        }
        if (shouldLockout && UserManager.SupportsUserLockout)
        {
            // If lockout is requested, increment access failed count
            // which might lock out the user
            await UserManager.AccessFailedAsync(user.Id).WithCurrentCulture();
            if (await UserManager.IsLockedOutAsync(user.Id).WithCurrentCulture())
            {
                return SignInStatus.LockedOut;
            }
        }
        return SignInStatus.Failure;
    }
}

I hope it helps. Cheers

like image 41
Guilherme Duarte Avatar answered Oct 28 '22 05:10

Guilherme Duarte