Implement ASP.Net Identity 2.0 with IdentityDbcontext

May 2, 2014 at 4:42 AM
Edited May 2, 2014 at 4:43 AM
Hi,

Is there a good way to implement Identity 2.0 in your framework ?

I actually change DbContext with IdentityDbContext but the problem is to inherit all indetity entities with IObjectState.

To achieve that I used generic version of IdentityDbContext and inherit each class of identity framework and add IObjectState interface to them but then I was obligate to create each Id with Guid.New.

I have something like this :
public class AppUser : IdentityUser<string, AppLogin, AppUserRole, AppClaim>, IObjectState
    {
        public AppUser()
        {
            this.ObjectState = Pattern.Infrastructure.ObjectState.Added;
        }
}
public class AppUserRole : IdentityUserRole, IObjectState
    {
        public AppUserRole ()
        {
            this.ObjectState = Pattern.Infrastructure.ObjectState.Added;
        }
        [NotMapped]
        public ObjectState ObjectState { get; set; }
        [Key]
        [Column(Order = 0)]
        public override string RoleId { get; set; }
        [Key]
        [Column(Order = 1)]
        public override string UserId { get; set; }
}
public class AppRole : IdentityRole<string, AppUserRole>, IObjectState
    {
        public AppRole()
        {
            this.ObjectState = Pattern.Infrastructure.ObjectState.Added;
        }
        [NotMapped]
        public ObjectState ObjectState { get; set; }
}

public class AppLogin : IdentityUserLogin, IObjectState
    {
        public AppLogin ()
        {
            this.ObjectState = Pattern.Infrastructure.ObjectState.Added;
        }
        [NotMapped]
        public ObjectState ObjectState { get; set; }
        [Key]
        public override string UserId { get; set; }
    }

public class AppClaim : IdentityUserClaim, IObjectState
    {
        public AppClaim()
        {
            this.ObjectState = Pattern.Infrastructure.ObjectState.Added;
        }
        [NotMapped]
        public ObjectState ObjectState { get; set; }
        [Key]
        [Column(Order = 0)]
        public override int Id { get; set; }
        [Key]
        [Column(Order = 1)]
        public override string UserId { get; set; }
    }
And to create a new user something like that :
var context = new AppDbContext();
var userManager = new UserManager<AppUser, string>(new UserStore<AppUser, AppRole, string, AppLogin, AppUserRole, AppClaim>(context));
var roleManager = new RoleManager<AppRole, string>(new RoleStore<AppRole, string, AppUserRole>(context));

                
AppRole role = new AppRole() { ObjectState = Pattern.Infrastructure.ObjectState.Added, Id = Guid.NewGuid().ToString(), Name = "Admin" };

var rolesuccess = roleManager.Create(role);

AppUser user = new AppUser() { ObjectState = Pattern.Infrastructure.ObjectState.Added, Id = Guid.NewGuid().ToString(), Email = "example@example.com", UserName = "user1", LastName = "", FirstName = "", PhoneNumber = "0000000000" };


 var usersuccess = userManager.Create(user, "123456");
userManager.AddToRole(user.Id, role.Name);
Thanks for your answer.
May 3, 2014 at 3:41 PM
Edited May 3, 2014 at 3:43 PM
Ok, I understood that it was impossible to manage ObjectState correctly with identity without to inherit every identity interfaces and rewrite code entirely (UserStore, RoleStore, etc...).
So I decided to remove every ObjectState reference and mechanism since Entity framework manage it by itself by reactivating proxy object.
Configuration.ProxyCreationEnabled = true; in DataContext.


And to integrate it correctly in unity I did that:
.RegisterType<AppUserManager>(new PerRequestLifetimeManager())
.RegisterType<IUserStore<AppUser>, UserStoreRepository>(new PerRequestLifetimeManager())
Where UserStoreRepository is like that :
public class UserStoreRepository : UserStore<AppUser>
    {
        public UserStoreRepository(IDataContextAsync context)
            : base(context as DbContext)
        {

        }
    }
I think it's the better solution if you use EF and don't want to rewrite every Identity class.

Tell me if I'm wrong.

Ah also, if you want to change UserManager options you can do something like that :
public class AppUserManager : UserManager<AppUser>
    {
        public AppUserManager(IUserStore<AppUser> store):base(store)
        {
            var manager = this;
            // Configure validation logic for usernames
            manager.UserValidator = new UserValidator<AppUser>(manager)
            {
                AllowOnlyAlphanumericUserNames = false,
                RequireUniqueEmail = true
            };
            // Configure validation logic for passwords
            manager.PasswordValidator = new PasswordValidator
            {
                RequiredLength = 6,
                RequireNonLetterOrDigit = false,
                RequireDigit = false,
                RequireLowercase = false,
                RequireUppercase = false,
            };
            // 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 in here.
            manager.RegisterTwoFactorProvider("PhoneCode", new PhoneNumberTokenProvider<AppUser>
            {
                MessageFormat = "Your security code is: {0}"
            });
            manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider<AppUser>
            {
                Subject = "Security Code",
                BodyFormat = "Your security code is: {0}"
            });
            manager.EmailService = new EmailService();
            manager.SmsService = new SmsService();
        }
}
Hope it can help some.
Coordinator
May 6, 2014 at 5:28 PM
We will review this and possibly integrate this into the sample application (with some minor changes), will keep you updated.
Marked as answer by lelong37 on 6/3/2014 at 11:16 AM
Jul 15, 2014 at 7:27 AM
Hello Le,

Have you have the chance to write a sample of how to integrate your repository framework with Identity 2.0? Looking forward to hear about that, I could not really get something that I like.
Many thanks !!
Aug 12, 2014 at 3:26 AM
Hi Le,

I need to implement Identity too, do you have any solution for that?
VCardins, and do you have implemented something that worked fine?

Thanks.
Aug 12, 2014 at 3:35 AM
Hello Lommez, not really. I ended up giving up for a while. I've implemented membershipreboot http://brockallen.com/2014/02/11/introducing-identityreboot/. I'd like to hear from Le at least some guidance.
Lommez, if you wanna discuss about this, I'm open !
Aug 12, 2014 at 3:43 AM
VCardins,

Thanks for you reply, and i will take a look at IdentityReboot, looks interesting.
I would to discuss about that with you.
How do you prefer to talk? By e-mail? or another way?
Aug 12, 2014 at 3:44 AM
Add me on skype : vcardins
Coordinator
Aug 12, 2014 at 4:15 AM
We will not be implementing Identity, reason being is the frequency of changes and also due to the fact there are quite a few authentication and authorization strategies for ASP.NET. For now having a separate context (Bounded Db context Pattern) for authentication and/or authorization is acceptable.
Marked as answer by lelong37 on 8/11/2014 at 8:15 PM
Aug 13, 2014 at 8:35 AM
Lelong,
Could you give me a start point of how to implement the Identity?
I've passed all day trying to that, but didn't have success.
I would be very glad.

Thanks
Aug 28, 2014 at 9:53 AM
Hello Le,
Have you have the chance to write a sample with separate IdentityDBcontext (implemented authentication and authorization) integrated in your framework?
You know to help me?
Thanks
Aug 28, 2014 at 4:52 PM
For those looking for an smooth integration to Microsoft Identity, I found this project : https://github.com/imranbaloch/ASPNETIdentityWithOnion. It is not as robust as genericunitofworkandrepositories but it does the job well.
Aug 29, 2014 at 4:31 AM
Hi all,

After a time to research everywhere, finally I could integrate Microsoft Identity 2.0 with this framework. But i need to touch into the Identity 2.0 source code with some override function. If anyone interesting in, I will post my solution here.
Aug 29, 2014 at 10:08 AM
Hello LionKing1109,

can you post your solution, please....
My email: zolino11@azet.sk

Thanks
Aug 29, 2014 at 5:26 PM
I encourage you guys to take a look at the project https://github.com/imranbaloch/ASPNETIdentityWithOnion. It separate concerns very well. Check here the article: http://dotnet.dzone.com/articles/sample-onion-architecture-0.
LionKing1109, why dont you post your fork here?
Thanks !!
Sep 8, 2014 at 1:35 PM
Can you share your solution for that? Is that a separate datacontext?
Oct 6, 2014 at 7:55 PM
Hi, guys!

Vcardins, may you explain how you implement membershipreboot, http://brockallen.com/2014/02/11/introducing-identityreboot/, in Le's repository framework? I try, but i don't have sucess.

thanks for any helps
Oct 6, 2014 at 9:23 PM
vcardins wrote:
Hello Lommez, not really. I ended up giving up for a while. I've implemented membershipreboot http://brockallen.com/2014/02/11/introducing-identityreboot/. I'd like to hear from Le at least some guidance.
Lommez, if you wanna discuss about this, I'm open !
Hi, guys!

Vcardins, may you explain how you implement membershipreboot, http://brockallen.com/2014/02/11/introducing-identityreboot/, in Le's repository framework? I try, but i don't have sucess.

thanks for any helps
Nov 5, 2014 at 12:15 AM
Hi, I trying to implement Identity as well but I have a problem when I access a user using the repository. The value assigned to ObjectState of the just queried user is "Added". So when I try to save anything else an error appears because it tries to add the user again. For a "non-Identity entity" everything works well but for "Identity entities" the ObjectState for queried entities is "Added".

Somebody knows how to synchronize correctly the ObjectState to "Unchanged" for queried entities? Or some way to tackle my problem?

Thanks in advance.
Feb 12, 2015 at 10:44 AM
Hi LionKing1109,

can you please post your solution.. Either here or to my email ppusapati@gmail.com

Regards,
Praveen
Feb 13, 2015 at 3:15 AM
Hey Alan, so sorry I missed that message. I know it was long ago, but if it is on, drop me a line. I've implemented MR nicely.
Mar 9, 2015 at 2:18 PM
Hi All,

I'm new to repository frameworks, IoC & DDD and although this framework appears to be an elegant design, I also need Identity integrated so was pleased to find this discussion!

I've looked at vcardins recommended ASPNETIdentityWithOnion and built some trial projects with that but would prefer to use this framework so started looking at fitting the Identity logic from that framework into this one. Unfortunately my ignorance is getting in the way, significantly my lack of understanding of Autofac & Unity and therefore how to implement Unity startup for the Identity types and dbcontext, as coded for Autofac in ASPNETIdentityWithOnion.

If anyone has any examples they could share, I'd be very appreciative!

Regards
Jerry
Mar 14, 2015 at 1:42 AM
Hi everyone, I have a question, I don't know how to at least Add a User to a Role with this framework its very nice and Ive been working with a lot, but sometimes its too rigid, for example Ive been trying to do this
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
    await UserManager.AddToRoleAsync(user.Id, @"JobProvider");
}
There is an exeption because it says that "Unable to cast IdentityUserRole to IObjectState" like I said I don't know how to figure it out please if you have a solution for my issue I'll appreciate you all,

Thanks
Sep 3, 2015 at 3:03 PM
Edited Sep 3, 2015 at 3:07 PM
I'm not sure if this is still of interest, but I have had good success integrating ASP.NET Identity Framework (version 2.21). Following on from Dragouf's suggestion (back in May), this is what I did:

For better housekeeping, I pulled out the ASP.NET Identity into four modules:

Identity - contains definitions for ApplicationRoleManager, ApplicationRoleStore, ApplicationSignInManager, ApplicationUserManager and ApplicationUserStore. These are just customised versions of the Identity counterparts.
Identity.Models - contains customised versions of the five standard Identity models plus any additional custom data entities you want to add to your User profile
Identity.Resources - contains any resource strings that you want to use in your models/UI (we're developing for a multi-national audience)
Identity.UI - contains some extensions and helper methods, for example, converting User Roles in a SelectListItem collection

In terms of customising the Identity models, I simply followed the ASP.NET Team's guidelines. In the examples, they change the Identity Primary Key from a 128-character string to an integer. In my case I converted the Primary Key to a GUID and also implemented the IObjectState interface on each of the customised Identity models. For the customised UserStore and RoleStore classes, I followed Dragouf's approach:
public class ApplicationUserStore : UserStore<ApplicationUser, ApplicationRole, Guid,
    ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
{
    public ApplicationUserStore(IMyDataContextAsync context)
        : base(context as DbContext)
    {
    }
}
I also re-enabled Lazy Loading and Proxy Creation in the base constructor of my data context class. Im my case I found this to be necessary to attach the custom 'UserDetails' entity to my Identity retrieved User. If you are not extending the User entity set then this may not be necessary.
Configuration.LazyLoadingEnabled = true;
Configuration.ProxyCreationEnabled = true;
after adding the necessary data set definitions to the data context:
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
public DbSet<ApplicationRole> ApplicationRoles { get; set; }
public DbSet<ApplicationUserRole> ApplicationUserRoles { get; set; }
public DbSet<ApplicationUserClaim> ApplicationUserClaims { get; set; }
public DbSet<ApplicationUserLogin> ApplicationUserLogins { get; set; }
public DbSet<ApplicationUserDetails> ApplicationUserDetails { get; set; }  // custom/application specific user data
The final part of the integration was to update the OWIN configuration and the DI (I'm using AutoFac) to reference the correct data context and model types. So far I have done limited testing, but all appears to be working well with all models running under a single data context and without any need to modify the standard URF code. I'll report back if I find any problems.
Sep 4, 2015 at 8:33 AM
Hey, thanks for the constructive replies.

I was wondering if now anyone had a robust approach for integrating Identity ?
Sep 4, 2015 at 8:38 AM
I am not sure what you mean by 'robust'. The route I described above appears to work correctly within the URF data context, at least with the current ASP.NET Identity version, and only took about an hour or so to implement.
Sep 21, 2015 at 4:24 PM
Neilski wrote:
I'm not sure if this is still of interest, but I have had good success integrating ASP.NET Identity Framework (version 2.21). Following on from Dragouf's suggestion (back in May), this is what I did:
Can you please provide a sample about URF and Identity 2. I'm interesting with this issue and I can't do it myself. Thank you.
Sep 23, 2015 at 8:22 PM
Several people in this thread claim they have successfully integrated ASP.NET Identity 2 with Le's framework. It would be of great service to the community if you could post your solutions or at least a more detailed guide on how you accomplished it. Some of us are new to many of these concepts and the documentation out there is not consistent. You would be heroes to many of us. Thanks.
Sep 24, 2015 at 8:13 AM
Edited Sep 24, 2015 at 2:32 PM
I've had a shot at this. You should be able to download a working project from https://github.com/Neilski/URF-Identity - hopefully it will be useful.

It's a slightly unusual demo project in as much that...
  1. It makes heavy use of external class libraries, and...
  2. Most of the strings are provided by resource (.resx) files
See the project's README.md file for more information.
Sep 24, 2015 at 3:39 PM
Thank you very much Neilski. This is exactly what I needed!
Sep 24, 2015 at 3:44 PM
Thank you very much Neilski for doing this. Have you considered posting this as an article at CodeProject? You could get exposure and win some prizes along the way. I'm sure there are many of us who were stuck trying to make this work.

Sep 24, 2015 at 3:46 PM
No problem. Can you do me a favour and let me know if you have any problems downloading, configuring and running the sample? If I can fix/make things easier sooner rather than later it might save some frustration down the line. Thanks.
Sep 24, 2015 at 3:55 PM
I'm not sure I feel that comfortable shouting about this. In reality I am just a jobbing developer and I'm not sure that what I have written warrants too much exposure, but if it helps someone then good enough - I'm more of a keep quiet and hope for the best sort of bloke, but thank you for the suggestion.
Sep 24, 2015 at 4:20 PM
I have tested your project. It works like a charm as is. This will help me tremendously with a project I'm working on. Thanks again.
Sep 24, 2015 at 4:25 PM
Thanks for letting me know - pleased it works for you - good luck with your project.
Nov 17, 2015 at 4:32 PM
Thank you Neilski. it was a big pain.

By the way i found an another project using URF + Identitiy named BeYourMarket which one is more confused me :)

https://github.com/beyourmarket/beyourmarket
Nov 18, 2015 at 8:01 AM
If anyone has used the first version of this, you should check out the latest version at https://github.com/Neilski/URF-Identity which uses the latest version of URF and also fixes some bugs in the original code.
Coordinator
Nov 18, 2015 at 11:59 PM
Thanks Neilski, I've updated our docs with your implementation/example.

https://genericunitofworkandrepositories.codeplex.com/documentation
Nov 19, 2015 at 12:53 PM
Thank you Neilski. I'm excercising your code. My i ask you what is the and where to use ApplicationUserService?

And btw i have troubleshooting with C#6 features. It wont compile somtimes.
Nov 19, 2015 at 1:17 PM
Edited Nov 19, 2015 at 1:18 PM
Hello, you may not want/need to use the ApplicationUserService, but it is there, and can be extended, if you want to access the ApplicationUser data graph outside of the Identity sub-system. Generally, you would probably not want to do this as it would be easy to corrupt the data that Identity manages directly, but sometimes you may want to. For example, you may want to retrieve a specific view that contains/references the ApplicationUser entity - the ApplicationUserService would be a convenient place to do this - but use with caution!

What compilation errors are you getting?
Nov 19, 2015 at 2:26 PM
I see. Well, is there any special reason IApplicationRoleService and IApplicationUserService does not inherits from IService<TEntity> but ApplicationUserService and IApplicationRoleService does from Service<TEntity>?

And that Abl projects. Are they your code? What does mean abl?


I didn't note the errors but at $ and => operators generally. Now its compiles. No problem but sometimes all C#6 features gives error. May be its about the my system.
Nov 19, 2015 at 3:01 PM
You are quite right about the interfaces, I have updated the service interfaces to inherit from IService<> - this is what happens if you rely on ReSharper too much!

The 'Abl' namespace references some class libraries and is derived from my company's name. In this application, the libraries really only provide some general purpose helper functions. Feel free to use them, or replace them with your own.

Let me know if you run across any further compilation issues. String interpolation etc. are C# version 6.0 features, so you may need to re-code these if running in an earlier environment.
Nov 19, 2015 at 4:51 PM
Edited Nov 19, 2015 at 4:52 PM
Thanks for your answers.

I've no problem with C# 6 features. Id googled and found whats wrong.
http://stackoverflow.com/a/31548221/1628636

I was looking for Identity and multi-language works with URF. With your works i found both :) thank you.

:) Now URF + Caching calling you. :)

Thanks for everything Neil, they are very usefull for me.
Nov 19, 2015 at 4:56 PM
My pleasure - pleased it has been of use.
Nov 22, 2015 at 12:47 PM
Edited Nov 22, 2015 at 12:48 PM
Hi there. Me again. I wanna ask another question.There is a line in Startup.Auth at end of the ApplicationUserManager method like below
            if (dataProtectionProvider != null)
            {
                manager.UserTokenProvider =
                    new DataProtectorTokenProvider<ApplicationUser, Guid>(
                        dataProtectionProvider.Create("UrfIdentity"));
            }
What the UrfIdentity plain text. Is it can be any text or is it depend to something another? Thank you again.
Nov 23, 2015 at 10:32 AM
The MSDN documentation is a little unclear as to the implications of using different string values. From the published examples, the string is set to "ASP.NET Identity", which is arguably more appropriate.

Other people may have more insight into this argument.
Nov 28, 2015 at 9:42 PM
Edited Nov 28, 2015 at 9:43 PM
Thank you.

I'd faced a problem with your project. I enabled google external auth. configured and its works but its not added user login details to AspNetLogins table. ProviderKey, UserId, LoginProvider.

Firstly i faced with that problem at my project. UserManager.AddLoginAsync, UserManager.AddToRoleAsync even UserManager.UpdateAsync not worked. They returns succeed but those funcs does not makes any changes.
var addLogin = await UserManager.AddLoginAsync(user.Id, info.Login)
if (addLogin.Succeeded)
{
       ...         
}
when i put mouse over the addLogin variable i can see the No Error(s) and Succeeded. But login details not stored in the database.

I also tried this
            user.Logins.Add(new ApplicationUserLogin
            {
                ProviderKey = info.Login.ProviderKey,
                LoginProvider = info.Login.LoginProvider,
                UserId = user.Id
            });

            var update = await UserManager.UpdateAsync(user);
Nothing happened. Seems Succeeded but its not. Can you please check if it is my mistake or there is something wrong with UrfIdentity when you have spare time? Thank you again.