Announcing preview of Microsoft.AspNet.Identity 2.0.0-alpha1

Announcing preview of Microsoft.AspNet.Identity 2.0.0-alpha1

Rate This
  • Comments 50

Today, we are releasing a preview of ASP.NET Identity. The main focus in this release was to fix issues with the 1.0 release and build upon the 1.0 Framework to add more features such as Account Confirmation, Password Reset etc. Please read the known issues section below before trying out this preview. 

Download this release

You can download ASP.NET Identity as preview NuGet packages from the NuGet gallery. You can install or update to these pre-release packages through NuGet using the NuGet Package Manager Console, like this:

  • Install-Package Microsoft.AspNet.Identity.EntityFramework –Version 2.0.0-alpha1 –Pre
  • Install-Package Microsoft.AspNet.Identity.Core -Version 2.0.0-alpha1 –Pre
  • Install-Package Microsoft.AspNet.Identity.OWIN -Version 2.0.0-alpha1 –Pre

Please remember to select the “Include Prerelease” option when searching for packages using the NuGet Package Manager or the Package Manager Console. For more information on how to install pre-release packages please read http://docs.nuget.org/docs/Reference/Versioning#Prerelease_Versions and http://docs.nuget.org/docs/release-notes/nuget-1.7#Show_prerelease_packages_in_the_Manage_NuGet_packages_dialog

 

What’s in this release

Following is the list of features and major issues that were fixed.

Account Confirmation

The ASP.NET Identity system now supports Account Confirmation. This is a fairly common scenario in most websites today where when you register for a new account on the website, you are required to confirm your email before you could do anything in the website. Email Confirmation is useful because it prevents bogus accounts from being created. This is extremely useful if you are using email as a method of communicating with the users of your website such as Forum sites, banking, ecommerce, social web sites.

Note: To send emails you can configure SMTP Server or use some of the popular email services such as SendGrid (http://sendgrid.com/windowsazure.html) which integrate nicely with Windows Azure and require no configuration on the application developer

In the sample project below, you need to hook up the Email service for sending emails. You will not be able to reset your password until you confirm your account 

Password Reset

Password Reset is a feature where the user can reset their passwords if they have forgotten their password.  

Security Token Provider

Support a way to regenerate the Security Token for the user in cases when the User changes there password or any other security related information such as removing an associated login(such as Facebook, Google, Microsoft Account etc). This is needed to ensure that any tokens generated with the old password are invalidated. In the sample project, if you change the users password then a new token is generated for the user and any previous tokens are invalidated. This feature provides an extra layer of security to your application since when you change your password, you will be logged out from everywhere (all other browsers) where you have logged into this application.

You can configure this in Startup.Auth.cs as follows. You can specify how often should the OWIN cookie middleware check if the Security Token for the current user is valid. This is in the sample project listed below.

Code Snippet
  1. // Enable the application to use a cookie to store information for the signed in user
  2. // and to use a cookie to temporarily store information about a user logging in with a third party login provider
  3. // Configure the sign in cookie
  4. app.UseCookieAuthentication(newCookieAuthenticationOptions {
  5.     AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
  6.     LoginPath = newPathString("/Account/Login"),
  7.     Provider = newCookieAuthenticationProvider {
  8.         OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
  9.             validateInterval: TimeSpan.FromSeconds(5),
  10.             regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
  11.     }
  12. });

 

Make the type of Primary Key be extensible for Users and Roles

In 1.0 the type of PK for Users and Roles was strings. This means when the ASP.NET Identity system was persisted in Sql Server using Entity Framework, we were using nvarchar. There were lots of discussions around this default implementation on Stack Overflow and based on the incoming feedback, we have provided an extensibility hook where you can specify what should be the PK of your Users and Roles table. This extensibility hook is particularly useful if you are migrating your application and the application was storing UserIds are GUIDs or ints.

Since you are changing the type of PK for Users and Roles, you need to plug in the corresponding classes for Claims, Logins which take in the correct PK. Following is a snippet of code which shows how you can change the PK to be int

Code Snippet
  1. publicclassApplicationUser : IdentityUser<int, CustomUserLogin, CustomUserRole, CustomUserClaim>
  2. {
  3. }
  4. publicclassCustomRole : IdentityRole<int, CustomUserRole>
  5. {
  6.     public CustomRole() { }
  7.     public CustomRole(string name) { Name = name; }
  8. }
  9. publicclassCustomUserRole : IdentityUserRole<int> { }
  10. publicclassCustomUserClaim : IdentityUserClaim<int> { }
  11. publicclassCustomUserLogin : IdentityUserLogin<int> { }
  12.  
  13. publicclassApplicationDbContext : IdentityDbContext<ApplicationUser, CustomRole, int, CustomUserLogin, CustomUserRole, CustomUserClaim>
  14. {
  15. }

 

Support IQueryable on Users and Roles

We have added support for IQueryable on UsersStore and RolesStore so you can easily get the list of Users and Roles.

For eg. the following code uses the IQueryable  and shows how you can get the list of Users from UserManager. You can do the same for getting list of Roles from RoleManager

Code Snippet
  1. //
  2. // GET: /Users/
  3. publicasyncTask<ActionResult> Index()
  4. {
  5.     return View(await UserManager.Users.ToListAsync());
  6. }

 

Support Delete operation through the UserManager

In 1.0, if you had to delete a User, you could not do it through the UserManager. We have fixed this issue in this release so you can do the following to delete a user

Code Snippet
  1. var user = await UserManager.FindByIdAsync(id);
  2.                 if (user == null)
  3.                 {
  4.                     return HttpNotFound();
  5.                 }
  6.                 var result = await UserManager.DeleteAsync(user);

 

UserManagerFactory Middleware

You can use Factory implementation to get an instance of UserManager from the OWIN context. This pattern is similar to what we use for getting AuthenticationManager from OWIN context for SignIn and SignOut. This is a recommended way of getting an instance of UserManager per request for the application.

Following snippet of code shows how you can configure this middleware in StartupAuth.cs. This is in the sample project listed below.

Code Snippet
  1. // Configure the UserManager
  2.             app.UseUserManagerFactory(newUserManagerOptions<ApplicationUserManager>()
  3.             {
  4.                 DataProtectionProvider = app.GetDataProtectionProvider(),
  5.                 Provider = newUserManagerProvider<ApplicationUserManager>()
  6.                 {
  7.                     OnCreate = ApplicationUserManager.Create
  8.                 }
  9.             });

Following snippet of code shows how you can get an instance of UserManager

Code Snippet
  1. HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();

 

DbContextFactory Middleware

ASP.NET Identity uses EntityFramework for persisting the Identity system in Sql Server. To do this the Identity System has a reference to the ApplicationDbContext. The DbContextFactory Middleware returns you an instance of the ApplicationDbContext per request which you can use in your application.

Following code shows how you can configure it in StartupAuth.cs. The code for this middleware is in the sample project.

Code Snippet
  1. app.UseDbContextFactory(ApplicationDbContext.Create);

Samples

  • We have a sample project which shows these new features at https://aspnet.codeplex.com. Please look for the Identity folder in the source. https://aspnet.codeplex.com/SourceControl/latest#Samples/Identity
    • This project shows how a ASP.NET Web Application project template would look like. Please look at the readme in the project for instructions on how to run.
  • For documentation on ASP.NET Identity 1.0 please visit http://www.asp.net/identity. We are working on adding more documentation on this site.

 

Known Issues/ Breaking change

As part of these new features such as Account Confirmation and Password Reset, we have added two new properties to the IdentityUser class namely ‘Email’ and ‘IsConfirmed’. This results in a change of the schema created by the ASP.NET Identity system in 2.0. Updating the packages to 2.0 in an existing application (which was using 1.0) will cause the application to fail since the underlying Entity Framework model has been changed. You need to update your database schema to use the 2.0 features. This can be done using Entity Framework migrations. For more details on how to update your application from 1.0 to 2.0, please visit this detailed blog post http://blogs.msdn.com/b/webdev/archive/2013/12/20/updating-asp-net-applications-from-asp-net-identity-1-0-to-2-0-0-alpha1.aspx

Note:

This is an area of migration which we are trying to see if we can provide a better story before we release the final version. Since the new features requires database schema updates, there is a user action involved to update the database manually. It is due to this reason that we have updated the package version to 2.0.0 as per SemVer guidelines, since on installing this version will break existing applications and you have to update the database schema.

ASP.NET Identity 2.0.0-alpha1 depends upon EntityFramework 6.1.0-alpha1 which was also released today (http://blogs.msdn.com/b/adonet/archive/2013/12/20/ef-6-1-alpha-1-available.aspx) since in EntityFramework 6.1.0-alpha1, there were bug fixes which helped in improving the migration scenario from Identity 1.0 – 2.0

 

Give feedback and get support

  • If you find any bugs please open them at our Codeplex Site where we track all our bugs https://aspnetidentity.codeplex.com/
  • If you want to discuss these features, please discuss them on Stack Overflow and use the following tag “asp.net-identity”

 

What’s next

We still have many bugs to fix and a few features to add before we release the final RTM version so do expect a few more previews in the coming months. You can check our roadmap at https://aspnetidentity.codeplex.com/wikipage?title=Roadmap

 

Thank You for trying out the preview and your feedback for ASP.NET

Leave a Comment
  • Please add 2 and 2 and type the answer here:
  • Post
  • In the roadmap page, aspnetidentity.codeplex.com/wikipage, it says:

    2.0.0 (Spring of 2013)

    It should be:

    2.0.0 (Spring of 2014)

  • Nm, I see the page has been updated.

    aspnetidentity.codeplex.com/wikipage

  • This link is not working: aspnet.codeplex.com/.../latest

  • Can you please provide an MVC 5 example for the PrimaryKeyConfigTest sample app? WebForm is obsolete (^^) and confuses the hell out of me nowadays! :-)

  • Found the MVC 5 demo. aspnet.codeplex.com/.../latest Samples->Identity->ChangePK->Identity-PasswordPolicy

  • @c. surieux: you can ignore the mapping of the phonenumber and phonenumberconfirmed property by adding an ignore statement in the modelcreating() method of the DBContext

    protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)

           {

               base.OnModelCreating(modelBuilder);

               modelBuilder.Entity<ApplicationUser>().Ignore(x => x.PhoneNumber);

               modelBuilder.Entity<ApplicationUser>().Ignore(x => x.PhoneNumberConfirmed);

           }

    The above code should skip the mapping for the phonenumber. You would still need to do migrations if you want to use the two factor auth feature

  • In Identity-PasswordPolice sample app. In the AccountController/ForgotPassword userId is used for the querystring:

                   var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);

    Then in ResetPassword mode.Email is used:

           // POST: /Account/ResetPassword

           [HttpPost]

           [AllowAnonymous]

           [ValidateAntiForgeryToken]

           public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)

           {

               if (ModelState.IsValid)

               {

                   var user = await UserManager.FindByNameAsync(model.Email);

                   if (user == null)

                   {

                       ModelState.AddModelError("", "No user found.");

                       return View();

                   }

                   IdentityResult result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);

                   if (result.Succeeded)

                   {

                       return RedirectToAction("ResetPasswordConfirmation", "Account");

                   }

                   else

                   {

                       AddErrors(result);

                       return View();

                   }

               }

               // If we got this far, something failed, redisplay form

               return View(model);

           }

    Shouldn't userId be used instead of the email to find the user?  

  • @Woot: FindById could be done too but finding by email adds an additional verification step in case the link was falsely obtained by somebody else since they would have to re enter the email.

  • Okey so the user id should not be sent in the querystring in the first place, correct?

  • Could you take a look at this question I posted on stackoverflow? Basically it's unclear to me how to tie in the new middleware to use the OAuthBearerTokens that are incorporated in the VS2013 SPA template (that uses Identity 1.0)

    stackoverflow.com/.../example-of-using-asp-net-identity-2-0-usermanagerfactory-with-useoauthbearertoke

  • I applied the beta NuGet packages to my alpha solution. I then used the pkg mgr console to Add-Migration [name] and Update-Database. The Update-Database failed when it tried to add indexes that already existed.

    AspNetUserLogins - IX_UserId

    AspNetUserRoles - IX_UserId, IX_RoleId

    AspNetUserClaims - IX_UserId (actually this worked since the existing index name was IX_User_Id)

    I renamed the existing indexes to prevent the collision and re-ran the Update-Database. I am not that familiar with how the migrations work so don't know why it thought it needed to create indexes that already existed.

    Gary Davis

  • Oops - the above comment should have been posted to the Beta1 comments.

    blogs.msdn.com/.../announcing-preview-of-microsoft-aspnet-identity-2-0-0-beta1.aspx

  • Asp.net V4.5, Web Forms, SQL Server for DB, Used VS2013 to generate a brand new project.

    Got it working.

    Upgraded to Identity 2.0 beta-1

    Understand the breaking changes - chose to just delete my DB and start over as there was nothing in it anyways.

    I also want to store PK as Int......used the Samples->ChangePK as a guide.....

    Now on the manage.aspx form generated by VS2013, i am getting an error on this line:

     private bool HasPassword(UserManager manager)

           {

               var user = manager.FindById(User.Identity.GetUserId());

               return (user != null && user.PasswordHash != null);

           }

    Error 1 Using the generic type 'Microsoft.AspNet.Identity.UserManager<TUser,TKey>' requires 2 type arguments C:\Data\Projects\VS2013\SHSR_DonorMgmt\SHSR_DonorMgmt\Account\Manage.aspx.cs

    I am sure it has to do with changing the PK to int....which was done as shown in the ChangePK Sample

    ( aspnet.codeplex.com/.../latest )

    Not really sure what to do to fix this issue (new to Identity stuff) so any help would be greatly appreciated.

  • @Paul you need to pass UserManager and int as arguments  to the HasPassword method. If you look at the sample aspnet.codeplex.com/.../latest then you will see the following code for HasPassword

    private bool HasPassword(ApplicationUserManager manager)

           {

               return manager.HasPassword<ApplicationUser,int>(Int32.Parse(User.Identity.GetUserId()));

           }

  • pranav, thanks....got it working.

    Still trying to get my head around some of these classes.....in a webform project (not mvc) how do i access the currently logged in user's ID?

    Thanks in advance

Page 3 of 4 (50 items) 1234