Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to setup custom schema for the new Microsoft.Asp.NET Identity (MVC5)

I have been struggling with the new Forms Identity process Microsoft introduced with the One Asp.Net implementation -- in particular with regards to Asp.NET MVC5.

My issues are twofold:

  1. How to point the context to a regular SQL instance instead of the LocalDb. At the very least LocalDb is not viable for me since my hosting provider does not support it.

  2. How to use a custom database for my identity entities.

I realize I could just change the connection string for the "DefaultConnection" entry in the Web.Config. But that still leaves me a series of tables prefixed with "AspNet" or some such.

Under the old MembershipProvider architecture, you could inherit from the providers and implement everything you needed in any way you want by placing entries in the Web.config that pointed the Forms Authentication process to your custom membership process.

With the new identity process, however, there are no hooks in the web.config to use. Additionally, inheriting from it is not any good as nothing appears to be virtual and to top it all off, it is inheriting from an existing context to boot.

I tried using my own context with entities implementing the appropriate new interfaces, but all it did was ignore my context completely and not only that, use localdb with a default DefaultConnection Connection String, ignoring my own context.

Since this is a new Microsoft brainchild, there are no real walkthroughs on how to customize the new process, just demos on how great the new process is.

I came across one entry out in the web that mentioned rolling out your own identity process and connect it to the OWIN process, but I am totally unfamiliar with OWIN and would need at least some info on how this could be done. (My initial foray into the OWIN project is not yielding any results)

Does anyone have any info?

like image 648
Gustyn Avatar asked Sep 22 '13 20:09

Gustyn


People also ask

How do I create a new Cshtml file?

Go to solution explorer => Views Folder => Right-click on “Home” Folder >> go to “Add” >> Click on [New Item] as follow. MVC 5 View Page(Razor) template from "Add New Item" window and provide the required name like "Index. cshtml" click on "Add" button.

How do you add the identity file in an existing ASP Net Web API core application?

Now, open the Startup configurations and add below code under ConfigureServices. This code will setup the database context. The second line configures the database which should be used for identity. AddIdentity(IServiceCollection) adds the default identity system configuration for the specified User and Role types.


1 Answers

Update: I am completely rewriting my answer because I have learned so much more about this process and realized that my answer was nowhere near complete enough.

First I created my entities, inheriting from the IdentyXXX classes of Identity (Only supplying one here for sample):

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using NTier.Web.Core.Interfaces.Common;
using NTier.Web.Core.Interfaces.DataModels;
using NTier.Web.Core.Interfaces.Stores;


namespace NTier.Web.DataAccess.Entities
{
    public sealed class MemberEntity : IdentityUser<Guid, MemberLogin, MemberRole, MemberClaim>,
        IMemberDataModel, IAuditable
    {

        public MemberEntity()
        {
            Id = Guid.NewGuid();
        }

        #region Overrides of IdentityUser<Guid,MemberLogin,MemberRole,MemberClaim>

        public override Guid Id
        {
            get { return base.Id; }
            set
            {
                base.Id = value != Guid.Empty ? value : base.Id;
            }
        }

        #region Overrides of IdentityUser<Guid,MemberLogin,MemberRole,MemberClaim>

        public override string PasswordHash
        {
            get { return base.PasswordHash; }
            set
            {
                base.PasswordHash = !string.IsNullOrWhiteSpace(value) ? value : base.PasswordHash ;
            }
        }

        #endregion

        #endregion

        public Guid Identity
        {
            get { return Id; }
            set
            {
                if (value != Guid.Empty)
                {
                    Id = value;
                }
            }
        }


        public string Moniker { get; set; }

        [MaxLength(256)]
        public string FirstName { get; set; }
        [MaxLength(256)]
        public string LastName { get; set; }
        [MaxLength(256)]
        public string Middle { get; set; }

        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<MemberEntity, Guid> 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;
        }

        #region Implementation of IAuditable
        public DateTime DateTimeCreated { get; set; }
        public DateTime? DateTimeModified { get; set; }
        public DateTime? DateTimeDeleted { get; set; }
        public DateTime? DateTimeArchived { get; set; }
        public string CreatedBy { get; set; }
        public string ModifiedBy { get; set; }
        public string DeletedBy { get; set; }
        public string ArchivedBy { get; set; }
        public bool IsDeleted { get; set; }
        public bool IsArchived { get; set; }
        #endregion
    }
}

Second, I overrode the OnModelCreating method in my DbContext like so:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            if (modelBuilder == null) throw new ArgumentNullException("modelBuilder");

            modelBuilder.Entity<WebSiteEntity>()
                        .HasKey(site => site.Identity)
                        .ToTable("WebSite");

            #region Security

            modelBuilder.Entity<MemberEntity>()
                        .ToTable("Member")
                        .HasMany(u => u.Roles)
                        .WithRequired()
                        .HasForeignKey(ur => ur.UserId);
            modelBuilder.Entity<MemberEntity>()
                        .HasMany(u => u.Claims)
                        .WithRequired()
                        .HasForeignKey(uc => uc.UserId);
            modelBuilder.Entity<MemberEntity>()
                        .HasMany(u => u.Logins)
                        .WithRequired()
                        .HasForeignKey(ul => ul.UserId);
            modelBuilder.Entity<MemberEntity>()
                        .Property(u => u.Moniker)
                        .HasMaxLength(50)
                        .HasColumnAnnotation("Index",
                                            new IndexAnnotation(new IndexAttribute("UserNameIndex")
                                                                {
                                                                    IsUnique = true,
                                                                    IsClustered = false,
                                                                    Order = 2
                                                                }))
                        .HasColumnAnnotation("Index",
                                            new IndexAnnotation(new IndexAttribute("MonikerIndex")
                                                                {
                                                                    IsUnique = true,
                                                                    IsClustered = false,
                                                                    Order = 1
                                                                }));
            modelBuilder.Entity<MemberEntity>()
                        .Property(u => u.LastName)
                        .HasMaxLength(256)
                        .HasColumnAnnotation("Index",
                                            new IndexAnnotation(new IndexAttribute("UserNameIndex")
                                                                {
                                                                    IsUnique = true,
                                                                    IsClustered = false,
                                                                    Order = 3
                                                                }))
                        .HasColumnAnnotation("Index",
                                            new IndexAnnotation(new IndexAttribute("MonikerIndex")
                                                                {
                                                                    IsUnique = true,
                                                                    IsClustered = false,
                                                                    Order = 2
                                                                }));
            ;
            modelBuilder.Entity<MemberEntity>()
                        .Property(u => u.FirstName)
                        .HasMaxLength(256)
                        .HasColumnAnnotation("Index",
                                            new IndexAnnotation(new IndexAttribute("UserNameIndex")
                                                                {
                                                                    IsUnique = true,
                                                                    IsClustered = false,
                                                                    Order = 4
                                                                }))
                        .HasColumnAnnotation("Index",
                                            new IndexAnnotation(new IndexAttribute("MonikerIndex")
                                                                {
                                                                    IsUnique = true,
                                                                    IsClustered = false,
                                                                    Order = 3
                                                                }));
            ;
            modelBuilder.Entity<MemberEntity>()
                        .Property(u => u.Middle)
                        .HasMaxLength(256);
            modelBuilder.Entity<MemberEntity>()
                        .Property(u => u.UserName)
                        .IsRequired()
                        .HasMaxLength(256)
                        .HasColumnAnnotation("Index",
                                            new IndexAnnotation(new IndexAttribute("UserNameIndex")
                                                                {
                                                                    IsUnique = true,
                                                                    IsClustered = false,
                                                                    Order = 1
                                                                }))
                        .HasColumnAnnotation("Index",
                                            new IndexAnnotation(new IndexAttribute("MonikerIndex")
                                                                {
                                                                    IsUnique = true,
                                                                    IsClustered = false,
                                                                    Order = 4
                                                                }));
            modelBuilder.Entity<MemberEntity>()
                        .Property(u => u.Email)
                        .HasMaxLength(256);
            modelBuilder.Entity<MemberRole>()
                        .HasKey(userRole => new
                                            {
                                                userRole.UserId,
                                                userRole.RoleId
                                            })
                        .ToTable("MemberRole");
            modelBuilder.Entity<MemberLogin>()
                        .HasKey(login => new
                                        {
                                            login.UserId,
                                            login.ProviderKey,
                                            login.LoginProvider
                                        })
                        .ToTable("MemberLogin");
            modelBuilder.Entity<MemberClaim>()
                        .ToTable("MemberClaim");
            modelBuilder.Entity<RoleEntity>()
                        .ToTable("Role");
            modelBuilder.Entity<RoleEntity>()
                        .Property(r => r.Name)
                        .IsRequired()
                        .HasMaxLength(256)
                        .HasColumnAnnotation("Index",
                                            new IndexAnnotation(new IndexAttribute("RoleNameIndex")
                                                                {
                                                                    IsUnique = true
                                                                }));
            modelBuilder.Entity<RoleEntity>()
                        .HasMany(r => r.Users)
                        .WithRequired()
                        .HasForeignKey(ur => ur.RoleId);

            #endregion
like image 141
Gustyn Avatar answered Oct 05 '22 20:10

Gustyn