Search code examples
azureasp.net-identity

ASP.NET Identity using Azure Active Directory... when/how are AspNetUsers db records created


I have a simple MVC .Core 6 web application that will be used on the corporate extranet (via an azure app service).

I've setup Microsoft Identity for login/authentication. This works really well. User requests a page and they're sent off to the corporate azure active directory login page (include 2fa) and returned to the application authenticated with user claims.

BUT... my Identity database tables remain empty (AspNetUsers et al). I was half expecting a record to be created representing the user that just signed in.

I scaffolded the ExternalLogin.cshtml page expecting it to be displayed after a user logs in (and there I could manually create the user if userManager.GetUserAsync(User) == null). But the page is never shown

I think I want AspNetUsers table entries because my simple app does a bit of audit trail stuff (CreatedByUserId, LastUpdatedByUserId) and I would like these to be foreign keys to the AspNetUsers table.

Thoughts? Are my expectations out of whack?


Solution

  • I was way off base on this.

    Microsoft.Identity.Web and Microsoft.Identity.Web.UI don't need/create AspNetUsers table (et al).

    If you want to build your own users table when a user logs in to the application you can do the following:

    builder.Services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, opts =>
    {
        opts.Events = new OpenIdConnectEvents()
        {
            OnTicketReceived = async (context) =>
            {
                //
                // Pull out the user details
                //
                var objectidentifier = context.Principal.FindFirstValue("http://schemas.microsoft.com/identity/claims/objectidentifier");
                var nameidentifier = context.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
                var name = context.Principal.FindFirstValue("name");
                var email = context.Principal.FindFirstValue("preferred_username");
    
                // 
                // Demo code to create a record in a users db table
                //
                using var scope = context.HttpContext.RequestServices.CreateScope();
                var ctx = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
                var isUserExists = await ctx.MyApplicationUser.AnyAsync(u => u.ObjectIdentifier == objectidentifier);
                if (!isUserExists)
                {
                    var applicationUser = new MyApplicationUser()
                    {
                        ObjectIdentifier = objectidentifier,
                        NameIdentifier = nameidentifier,
                        Email = email,
                        Name = name,
                    };
                    ctx.MyApplicationUser.Add(applicationUser);
                    await ctx.SaveChangesAsync();
                };
            }
        };
    });
    

    Note that some care is needed to pull out the correct claims.

    Note this should probably update an existing user if their details changed (names do change).

    This is slightly modified from what I found at: https://dotnetthoughts.net/azure-active-directory-b2c-in-aspnet-core-mvc-part1/