aspnetcore icon indicating copy to clipboard operation
aspnetcore copied to clipboard

Adding Roles to a Blazor Web project does not work

Open csharpfritz opened this issue 1 year ago • 4 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Describe the bug

When attempting to add Roles to Identity in a Blazor project, errors are returned and its unable to proceed.

Given the default configuration in the Blazor Web template:

builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
		.AddEntityFrameworkStores<ApplicationDbContext>()
		.AddSignInManager()
		.AddDefaultTokenProviders();

When .AddRoles<IdentityRole>() is added the following error is reported:

System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.RoleManager`1[Microsoft.AspNetCore.Identity.IdentityRole`1[System.String]] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager`1[Microsoft.AspNetCore.Identity.IdentityRole`1[System.String]]': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IRoleStore`1[Microsoft.AspNetCore.Identity.IdentityRole`1[System.String]]' while attempting to activate 'Microsoft.AspNetCore.Identity.RoleManager`1[Microsoft.AspNetCore.Identity.IdentityRole`1[System.String]]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory`1[BlazorApp1.Data.ApplicationUser] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory`2[BlazorApp1.Data.ApplicationUser,Microsoft.AspNetCore.Identity.IdentityRole`1[System.String]]': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IRoleStore`1[Microsoft.AspNetCore.Identity.IdentityRole`1[System.String]]' while attempting to activate 'Microsoft.AspNetCore.Identity.RoleManager`1[Microsoft.AspNetCore.Identity.IdentityRole`1[System.String]]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.ISecurityStampValidator Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.SecurityStampValidator`1[BlazorApp1.Data.ApplicationUser]': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IRoleStore`1[Microsoft.AspNetCore.Identity.IdentityRole`1[System.String]]' while attempting to activate 'Microsoft.AspNetCore.Identity.RoleManager`1[Microsoft.AspNetCore.Identity.IdentityRole`1[System.String]]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.ITwoFactorSecurityStampValidator Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.TwoFactorSecurityStampValidator`1[BlazorApp1.Data.ApplicationUser]': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IRoleStore`1[Microsoft.AspNetCore.Identity.IdentityRole`1[System.String]]' while attempting to activate 'Microsoft.AspNetCore.Identity.RoleManager`1[Microsoft.AspNetCore.Identity.IdentityRole`1[System.String]]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.SignInManager`1[BlazorApp1.Data.ApplicationUser] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.SignInManager`1[BlazorApp1.Data.ApplicationUser]': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IRoleStore`1[Microsoft.AspNetCore.Identity.IdentityRole`1[System.String]]' while attempting to activate 'Microsoft.AspNetCore.Identity.RoleManager`1[Microsoft.AspNetCore.Identity.IdentityRole`1[System.String]]'.)'

Expected Behavior

RoleManager is configured and we are able to use IdentityRole references in a blazor project

Steps To Reproduce

Add .AddRoles<IdentityRole>() to the configuration of Identity in a Blazor web application

Exceptions (if any)

System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.RoleManager1[Microsoft.AspNetCore.Identity.IdentityRole1[System.String]] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager1[Microsoft.AspNetCore.Identity.IdentityRole1[System.String]]': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IRoleStore1[Microsoft.AspNetCore.Identity.IdentityRole1[System.String]]' while attempting to activate 'Microsoft.AspNetCore.Identity.RoleManager1[Microsoft.AspNetCore.Identity.IdentityRole1[System.String]]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory1[BlazorApp1.Data.ApplicationUser] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory2[BlazorApp1.Data.ApplicationUser,Microsoft.AspNetCore.Identity.IdentityRole1[System.String]]': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IRoleStore1[Microsoft.AspNetCore.Identity.IdentityRole1[System.String]]' while attempting to activate 'Microsoft.AspNetCore.Identity.RoleManager1[Microsoft.AspNetCore.Identity.IdentityRole1[System.String]]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.ISecurityStampValidator Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.SecurityStampValidator1[BlazorApp1.Data.ApplicationUser]': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IRoleStore1[Microsoft.AspNetCore.Identity.IdentityRole1[System.String]]' while attempting to activate 'Microsoft.AspNetCore.Identity.RoleManager1[Microsoft.AspNetCore.Identity.IdentityRole1[System.String]]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.ITwoFactorSecurityStampValidator Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.TwoFactorSecurityStampValidator1[BlazorApp1.Data.ApplicationUser]': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IRoleStore1[Microsoft.AspNetCore.Identity.IdentityRole1[System.String]]' while attempting to activate 'Microsoft.AspNetCore.Identity.RoleManager1[Microsoft.AspNetCore.Identity.IdentityRole1[System.String]]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.SignInManager1[BlazorApp1.Data.ApplicationUser] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.SignInManager1[BlazorApp1.Data.ApplicationUser]': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IRoleStore1[Microsoft.AspNetCore.Identity.IdentityRole1[System.String]]' while attempting to activate 'Microsoft.AspNetCore.Identity.RoleManager1[Microsoft.AspNetCore.Identity.IdentityRole`1[System.String]]'.)'

.NET Version

8.0.0

Anything else?

No response

csharpfritz avatar Dec 22 '23 17:12 csharpfritz

It does work, but you have to add roles first:

builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddRoles<IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddSignInManager() .AddDefaultTokenProviders();

woha avatar Dec 23 '23 09:12 woha

A slight modification to your code, adding the IdentityRole type to the AddRoles command and this syntax works in a new application.

In my existing application that I am migrating, I receive an error

"System.InvalidOperationException: 'Scheme already exists: Identity.Application'"

csharpfritz avatar Dec 26 '23 15:12 csharpfritz

This is fine for a Server app, but what about a WebAssembly app? Is there an easy way to add roles on the client without major surgery?

carlfranklin avatar Dec 31 '23 22:12 carlfranklin

AddEntityFrameworkStores must be called after AddRoles because it reads builder.RoleType which needs to first be set by AddRole. It appears to have always been that way, so I'm not sure why I haven't seen complaints before. Maybe because people usually call AddIdentity<TUser, TRole>? You'd think you'd see the same problem with AddDefaultIdentity<TUser> though.

This doesn't seem easy to make order independent without some major surgery which I'm not sure is worthwhile. I think we need to find a way to make the error clearer (possibly with an analyzer or a runtime error) if AddEntityFrameworkStores is called before AddRole and update the documentation for both AddEntityFrameworkStores and AddRole to call this out.

In my existing application that I am migrating, I receive an error

"System.InvalidOperationException: 'Scheme already exists: Identity.Application'"

@csharpfritz Do you still have access to this application? Is it possible that you is more than one call to AddIdentity, AddDefaultIdentity, AddIdentityCookies, AddApplicationCookie, and/or AddIdentityApiEndpoints? I wonder if it would be too breaking to not re-add the "Identity.Application" scheme if it has already been added, but still allow any Action<IdentityCookiesBuilder> configureCookies callbacks to run in the order they are added.

halter73 avatar Feb 23 '24 03:02 halter73