29

By default ASP.NET Identity in VS 2015 uses a string as a primary key for AspNet*** tables. I wanted to to use int-typed id's instead. After some research it turned out that different typed id's are supported by the framework out of the box. In the answer below I will show what changes to make to achieve that.

UPDATE: After adding my answer I found this blog post on asp.net site that describes the same but more comprehensive: http://www.asp.net/identity/overview/extensibility/change-primary-key-for-users-in-aspnet-identity

2 Answers 2

47
  1. IdentityModels.cs change to this:

    // New derived classes
    public class UserRole : IdentityUserRole<int>
    {
    }
    
    public class UserClaim : IdentityUserClaim<int>
    {
    }
    
    public class UserLogin : IdentityUserLogin<int>
    {
    }
    
    public class Role : IdentityRole<int, UserRole>
    {
        public Role() { }
        public Role(string name) { Name = name; }
    }
    
    public class UserStore : UserStore<ApplicationUser, Role, int,
        UserLogin, UserRole, UserClaim>
    {
        public UserStore(ApplicationDbContext context): base(context)
        {
        }
    }
    
    public class RoleStore : RoleStore<Role, int, UserRole>
    {
        public RoleStore(ApplicationDbContext context): base(context)
        {
        }
    }
    
    // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
    public class ApplicationUser : IdentityUser<int, UserLogin, UserRole, UserClaim>
    {
        public DateTime? ActiveUntil;
    
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(ApplicationUserManager manager)
        {
            // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Add custom user claims here
            return userIdentity;
        }
    }
    
    public class ApplicationDbContext : IdentityDbContext<ApplicationUser, Role, int,
        UserLogin, UserRole, UserClaim>
    {
        public ApplicationDbContext()
            : base("DefaultConnection")
        {
        }
    
        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }
    }
    
  2. In `App_Start\IdentityConfig.cs, change the following classes:

    public class ApplicationUserManager : UserManager<ApplicationUser, int>
    {
        public ApplicationUserManager(IUserStore<ApplicationUser, int> store)
            : base(store)
        {
        }
    
        public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
        {
            var manager = new ApplicationUserManager(new UserStore(context.Get<ApplicationDbContext>()));
            // Configure validation logic for usernames
            manager.UserValidator = new UserValidator<ApplicationUser, int>(manager)
            {
                AllowOnlyAlphanumericUserNames = false,
                RequireUniqueEmail = true
            };
    
            // Configure validation logic for passwords
            manager.PasswordValidator = new PasswordValidator
            {
                RequiredLength = 8,
                // RequireNonLetterOrDigit = true,
                RequireDigit = true,
                RequireLowercase = true,
                RequireUppercase = true,
            };
    
            // Configure user lockout defaults
            manager.UserLockoutEnabledByDefault = true;
            manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
            manager.MaxFailedAccessAttemptsBeforeLockout = 5;
    
            // Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
            // You can write your own provider and plug it in here.
            manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser, int>
            {
                MessageFormat = "Your security code is {0}"
            });
            manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser, int>
            {
                Subject = "Security Code",
                BodyFormat = "Your security code is {0}"
            });
            manager.EmailService = new EmailService();
            manager.SmsService = new SmsService();
            var dataProtectionProvider = options.DataProtectionProvider;
            if (dataProtectionProvider != null)
            {
                manager.UserTokenProvider = 
                    new DataProtectorTokenProvider<ApplicationUser, int>(dataProtectionProvider.Create("ASP.NET Identity"));
            }
            return manager;
        }
    }
    
    // Configure the application sign-in manager which is used in this application.
    public class ApplicationSignInManager : SignInManager<ApplicationUser, int>
    {
        public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager)
            : base(userManager, authenticationManager)
        {
        }
    
        public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
        {
            return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
        }
    
        public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context)
        {
            return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication);
        }
    }
    
  3. In App_Start\Startup.Auth.cs change OnValidateIdentity property to this:

    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser, int>(
        validateInterval: TimeSpan.FromMinutes(30),
        regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager),
        getUserIdCallback: id => id.GetUserId<int>())
    
  4. Change ManageController to work with the new pk type:

Replace all entries of User.Identity.GetUserId() to User.Identity.GetUserId<int>()

There might be a couple of string id arguments that need to be changed to int, but that's about it.

Sign up to request clarification or add additional context in comments.

6 Comments

If you could highlight exactly what in your code was creating the int id that would be great thx.
Should we enable auto increment on Id filed of Users table??
@niico - as far as I remember the id fields in the auth db were set to auto increment
Hi, I dont have the OnValidateIdentity. Does it really matter?
what about other tables keys?? like "Role" table, or "UserRoles" table. thery are still nvarchar(MAX)!
|
19

Per this blog post, with ASP.NET Core Identity, make the following changes:

First, go to the Data\Migrations folder and delete everything in there.

In Startup.cs, in the ConfigureServices method, change services.AddIdentity to

services.AddIdentity<ApplicationUser, IdentityRole<int>>()
   .AddEntityFrameworkStores<ApplicationDbContext, int>()
   .AddDefaultTokenProviders();

In ApplicationDbContext.cs change the base class from IdentityDbContext<ApplicationUser> to

public class ApplicationDbContext
  : IdentityDbContext<ApplicationUser, IdentityRole<int>, int>

Finally, change the base class in ApplicationUser.cs from IdentityUser to

public class ApplicationUser : IdentityUser<int>

Then run add-migration -o Data\Migrations and update-database. If the migrations cause any issues, use Sql Server Management Studio or the SqlServerObjectExplorer in VS to delete the database (don't just use the file system), re-delete your migrations, and try again.

2 Comments

@VulovicVukasin Just trying to pay it forward from those on this site who helped me to those I can help. Best in your endeavors
For .NET Core 2.* and above, change .AddEntityFrameworkStores<ApplicationDbContext, int>() to .AddEntityFrameworkStores<ApplicationDbContext>() and it'll work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.