Getting Started with IdentityManager2

ASP.NET Identity

Swagger

IdentityManager is an open source project that offers a modern alternative to the ASP.NET WebSite Administration tool that used to come bundled with Visual Studio. IdentityManager offered a simple user interface that allowed developers to bootstrap a new user store with users and role data and saw considerable popularity despite never being intended for production. IdentityManager was designed for ASP.NET & OWIN, supporting ASP.NET Identity 2 and Membership Reboot, which bring us to the topic of this article.

Introducing IdentityManager II

And that’s not the usual hyped up title. I'm running this project; therefore I get to introduce/announce it and use a silly font on my website.

IdentityManager2 is currently a straight port of IdentityManager but now using ASP.NET Core and ASP.NET Core Identity (aka ASP.NET Identity 3). My employer, Rock Solid Knowledge, is taking ownership of the IdentityManager project from Brock Allen and will be the primary maintainers from here on. IdentityManager1 will remain a read-only project. For more details on the reasoning of the change in ownership see the announcement post from Brock and Rock Solid Knowledge.

IdentityManager2 will be a side project for me. Contributors are welcome, major or minor. However, if you want to tackle something meaty, please don’t stealth it. Get in contact, and I’ll be happy to talk through and help plan any major pull requests. Initial migration of the core repository was done by Paul Glasson; I just got to cherry pick the fun bits.

IdentityManager2 will remain a tool for developers. It will never offer production level user management or offer features outside of user management. For production level user management, see AdminUI.

Setting up IdentityManager2 with ASP.NET Core Identity

Creating an IdentityManager2 project is fairly simple. First, create a new ASP.NET Core Web Application, using the “Empty” template (empty isn’t necessary, just cleaner for a demo or a standalone project).

We then need to install IdentityManager2:

install-package IdentityManager2 -pre

We then need to register the IdentityManager2 dependencies within our ConfigureServices method:

services.AddIdentityManager();

And then register IdentityManager2 in our pipeline by using the following in our Configure method (this should go before any MVC usage):

app.UseIdentityManager();

That’s the basics of IdentityManager2 done. All we need to do now is to tell it how to interact with our user store, using an implementation of IIdentityManagerService. Out of the box an implementation for ASP.NET Core Identity is available, so let’s use that:

install-package IdentityManager2.AspNetIdentity -pre

We can then register this IdentityManagerService by chaining our AddIdentityManager call with:

services.AddIdentityManager()
  .AddIdentityMangerService<AspNetCoreIdentityManagerService<IdentityUser, string, 
    IdentityRole, string>>();

And then to get ASP.NET Core Identity working, we just need to register our stores and any dependences. So, using the default IdentityUser and IdentityDbContext, this would look like (where I’m just using an in-memory database found in the Microsoft.EntityFrameworkCore.InMemory package):

services.AddDbContext<IdentityDbContext>(opt => opt.UseInMemoryDatabase("test"));

services.AddIdentity<IdentityUser, IdentityRole>() .AddEntityFrameworkStores<IdentityDbContext>() .AddDefaultTokenProviders();

Note that the registration of token providers (for reset and confirmation) is currently required. You may also need to add the Microsoft.AspNetCore.Identity.EntityFrameworkCore package if you are not using the ASP.NET Core App/All style packages.

And that’s all there is to it!

Protecting IdentityManager2 with IdentityServer4

Out of the box, IdentityManager2 allows anyone running it locally full access. You can, however, change this to your own authentication method, including an OpenID Provider such as IdentityServer4. Let’s take a look at how we can protect IdentityManager2 with IdentityServer4.

First, let’s configure our hosting app to use cookies for storing identity data, and OpenID Connect to get identity data:

services.AddAuthentication()
    .AddCookie("cookie")
    .AddOpenIdConnect("oidc", opt =>
    {
        opt.Authority = "http://localhost:5001";
        opt.ClientId = "identitymanager2";
        
        // default: openid & profile
        opt.Scope.Add("roles");
    
        opt.RequireHttpsMetadata = false; // dev only
        opt.SignInScheme = "cookie";
    });

Now we need to configure IdentityManager2 to use these authentication schemes for authenticating and challenging users:

services.AddIdentityManager(opt =>
     opt.SecurityConfiguration =
         new SecurityConfiguration
         {
             HostAuthenticationType = "cookie",
             HostChallengeType = "oidc"
         });

Within IdentityServer, our client will look something like:

new Client
{
    ClientId = "identitymanager2",
    ClientName = "IdentityManager2",
    AllowedGrantTypes = GrantTypes.Implicit,
    RedirectUris = {"http://localhost:5000/signin-oidc"},
    AllowedScopes = {"openid", "profile", "roles"}
};

Where the role scope, simply allows IdentityManager to receive the role claim type for use in its authorization decision:

new IdentityResource("roles", new List<string> {"role"});

Authorization

For authorization, IdentityManager will automatically look for an identity role of type “role” with a value of “IdentityManagerAdministrator”. If your user does not have this claim, then they will receive a 403 Forbidden after authentication. Both the claim type and value used for authorization can be modified using the RoleClaimType and AdminRoleName properties on IdentityManager’s SecurityConfiguration options class.

By default, the Microsoft OpenID Connect middleware will transform claims from IdentityServer with the role claim type to a claim type of http://schemas.microsoft.com/ws/2008/06/identity/claims/role. So, either set IdentityManager’s RoleClaimType to this or simply do the following ceremony to prevent the map from happening:

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

For API authorization, IdentityManager2 currently uses a hacky port of the old OWIN OAuth middleware. I have long-running plans to update this, which you track here.

Creating your own IIdentityManagerService

If you have an existing IIdentityManagerService from IdentityManager1, then migration shouldn’t be too large of a task. Just be aware that some methods now have asynchronous alternatives that you may find useful. Take a look at the IdentityManager2.AspNetIdentity library for inspiration.

If you have a custom user store, then you will need to create your own IIdentityManagerService as an adaptor between the two systems. Again, check out the IdentityManager2.AspNetIdentity library for inspiration.

Source Code

Scott Brady

Scott Brady

Scott Brady is the Identity & Access Control Lead at Rock Solid Knowledge, focusing on authorization & authentication protocols such as OAuth and OpenID Connect.

Keep Up To Date

Sign up to the mailing list to keep up to date with the latest articles and announcements.

Follow