Open Closed

Openid administrator login #4893


User avatar
0
Frontis2 created
  • ABP Framework version: v7.1.1
  • UI type: MVC
  • DB provider: EF Core

Currently am trying to add an external login, using Azure Active Directory. The purpose of this external login, is to be used by administrators only.

As described in the community blog post, I did the following... Note the CustomOpenIdConnectEvents class...

private void ConfigureExternalProviders(ServiceConfigurationContext context, IConfiguration configuration)
    {
        context.Services.AddAuthentication()
          //Omitted other third party configurations
          .AddOpenIdConnect("AzureOpenId", "Sign in with Microsoft", options =>
          {
              options.Authority = $"https://login.microsoftonline.com/{configuration["AzureAd:TenantId"]}/v2.0/";
              options.ClientId = configuration["AzureAd:ClientId"];
              options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
              options.CallbackPath = configuration["AzureAd:CallbackPath"];
              options.ClientSecret = configuration["AzureAd:ClientSecret"];
              options.RequireHttpsMetadata = false;
              options.SaveTokens = true;
              options.GetClaimsFromUserInfoEndpoint = true;
              options.Scope.Add("email");
              options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub");
              options.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
              options.SignInScheme = IdentityConstants.ExternalScheme;

              options.EventsType = typeof(CustomOpenIdConnectEvents);
          });
    }

And here is the CustomOpenIdConnectEvents class:

    {
        [UnitOfWork]
        public override async Task TokenValidated(TokenValidatedContext context)
        {
            await base.TokenValidated(context);

            var userManager = context.HttpContext.RequestServices.GetRequiredService<IdentityUserManager>();
            

            var userEmail = context.Principal.FindFirstValue(ClaimTypes.Email);

            var currentUser = await userManager.FindByEmailAsync(userEmail);

            if (currentUser != null)
            {
                var adminRoleName = "admin"; // Replace with your admin role name
                var isInRole = await userManager.IsInRoleAsync(currentUser, adminRoleName);

                if (!isInRole)
                {
                    await userManager.AddToRoleAsync(currentUser, adminRoleName);
                    var identity = context.Principal.Identity as ClaimsIdentity;
                    identity?.AddClaim(new Claim(identity.RoleClaimType, adminRoleName));
                }
            }
        }
    }

The code itself is working. However with the following issues:

  • The user must log out and log back in, before he is admin
    • I think this is because the user account only exists after he hits "register".
  • Am not quite sure if finding the user based on the mail-address is save. However, finding by claim does not work. var currentUser = await userManager.GetUserAsync(context.Principal);

Concrete: How can I make sure users are automatically administrator? Preferably the registration form should be skipped.


1 Answer(s)
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    You can create a user if it doesn't exist:

    [UnitOfWork]
    public override async Task TokenValidated(TokenValidatedContext context)
    {
        await base.TokenValidated(context);
    
        var userManager = context.HttpContext.RequestServices.GetRequiredService();
        
    
        var userEmail = context.Principal.FindFirstValue(ClaimTypes.Email);
    
        var currentUser = await userManager.FindByEmailAsync(userEmail);
    
        if(currentUser == null)
        {
            // create a user
        }
        
        var adminRoleName = "admin"; // Replace with your admin role name
        var isInRole = await userManager.IsInRoleAsync(currentUser, adminRoleName);
    
        if (!isInRole)
        {
            await userManager.AddToRoleAsync(currentUser, adminRoleName);
            var identity = context.Principal.Identity as ClaimsIdentity;
            identity?.AddClaim(new Claim(identity.RoleClaimType, adminRoleName));
        }
        
    }
    
Made with ❤️ on ABP v9.1.0-preview. Updated on November 11, 2024, 11:11