admin管理员组

文章数量:1278826

I would like to setup authentication and authorization for my project, I have a little experience with identity server as most of my clients use it but since it mostly is setup, I don't have experience in setting it up myself.

I'm looking at the documentation samples, codemaze and everything else but I'm stuck. The documentation is to authenticate the frontend to the backend where I like to use username and password, 2FA, ....

My project is going to be a medium sized micro service architecture, which is currently orchestrated in .NET Aspire and using .NET 8.0.

I already setup duende.identityserver as an API purely backend.

For the frontend, I'm going with a Blazor web app or Blazor server and wasm. This template creates 2 assemblies - client and server. Since I want usernames and passwords I went with the account type "individual accounts", this gives me all the pages that I want.

Except there is a problem in the server assembly there is also logic that is already in my backend identity server API project, mainly the ApplicationDbContext and migrations.

I tried to delete this code and obviously I f*d up. Anyway I can't run my frontend as it is giving me a dependency injection error on UserManager.

I tried to add this even tough it was never there.

builder.Services.AddScoped<UserManager<ApplicationUser>>();
builder.Services.AddScoped<SignInManager<ApplicationUser>>();

Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IUserStore1[Xyflux.Frontend.Data.ApplicationUser]' while attempting to activate 'Microsoft.AspNetCore.Identity.UserManager1[Xyflux.Frontend.Data.ApplicationUser]'

System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.UserManager1[Xyflux.Frontend.Data.ApplicationUser] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager1[Xyflux.Frontend.Data.ApplicationUser]': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IUserStore1[Xyflux.Frontend.Data.ApplicationUser]' while attempting to activate 'Microsoft.AspNetCore.Identity.UserManager1[Xyflux.Frontend.Data.ApplicationUser]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.SignInManager1[Xyflux.Frontend.Data.ApplicationUser] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.SignInManager1[Xyflux.Frontend.Data.ApplicationUser]': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IUserStore1[Xyflux.Frontend.Data.ApplicationUser]' while attempting to activate 'Microsoft.AspNetCore.Identity.UserManager1[Xyflux.Frontend.Data.ApplicationUser]'.) (Error while validating the service descriptor 'ServiceType: Xyflux.Frontend.Components.Account.IdentityUserAccessor Lifetime: Scoped ImplementationType: Xyflux.Frontend.Components.Account.IdentityUserAccessor': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IUserStore1[Xyflux.Frontend.Data.ApplicationUser]' while attempting to activate 'Microsoft.AspNetCore.Identity.UserManager1[Xyflux.Frontend.Data.ApplicationUser]'.)'

And full DI

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Xyflux.Frontend.Components;
using Xyflux.Frontend.Components.Account;
using Xyflux.Frontend.Data;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents()
    .AddInteractiveWebAssemblyComponents();

builder.Services.AddCascadingAuthenticationState();
builder.Services.AddScoped<UserManager<ApplicationUser>>();
builder.Services.AddScoped<SignInManager<ApplicationUser>>();
builder.Services.AddScoped<IdentityUserAccessor>();
builder.Services.AddScoped<IdentityRedirectManager>();
builder.Services.AddScoped<AuthenticationStateProvider, PersistingRevalidatingAuthenticationStateProvider>();


builder.Services.AddBff();

builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
    options.Cookie.Name = "BlazorApp.Cookie";
    options.Cookie.HttpOnly = true;
    options.SlidingExpiration = true;
    options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
})
.AddOpenIdConnect("oidc", options =>
{
    options.Authority = "https://localhost:5001"; 
    options.ClientId = "blazor-client"; 
    options.ClientSecret = "your_client_secret"; 
    options.ResponseType = "code";
    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("api1");
    options.SaveTokens = true; 
    options.GetClaimsFromUserInfoEndpoint = true;
    options.ForwardSignIn = "";
    
});

builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = options.DefaultPolicy;
});

builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseWebAssemblyDebugging();
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see .
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseAuthentication();
app.UseAuthorization();

app.UseStaticFiles();
app.UseAntifery();

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode()
    .AddInteractiveWebAssemblyRenderMode()
    .AddAdditionalAssemblies(typeof(Xyflux.Frontend.Client._Imports).Assembly);

// Add additional endpoints required by the Identity /Account Razor components.
app.MapAdditionalIdentityEndpoints();

app.Run();

I'm also using the duende.bff framework.

Can somebody guide me what I did wrong and guide me what my next steps to do are?

I would like to setup authentication and authorization for my project, I have a little experience with identity server as most of my clients use it but since it mostly is setup, I don't have experience in setting it up myself.

I'm looking at the documentation samples, codemaze and everything else but I'm stuck. The documentation is to authenticate the frontend to the backend where I like to use username and password, 2FA, ....

My project is going to be a medium sized micro service architecture, which is currently orchestrated in .NET Aspire and using .NET 8.0.

I already setup duende.identityserver as an API purely backend.

For the frontend, I'm going with a Blazor web app or Blazor server and wasm. This template creates 2 assemblies - client and server. Since I want usernames and passwords I went with the account type "individual accounts", this gives me all the pages that I want.

Except there is a problem in the server assembly there is also logic that is already in my backend identity server API project, mainly the ApplicationDbContext and migrations.

I tried to delete this code and obviously I f*d up. Anyway I can't run my frontend as it is giving me a dependency injection error on UserManager.

I tried to add this even tough it was never there.

builder.Services.AddScoped<UserManager<ApplicationUser>>();
builder.Services.AddScoped<SignInManager<ApplicationUser>>();

Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IUserStore1[Xyflux.Frontend.Data.ApplicationUser]' while attempting to activate 'Microsoft.AspNetCore.Identity.UserManager1[Xyflux.Frontend.Data.ApplicationUser]'

System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.UserManager1[Xyflux.Frontend.Data.ApplicationUser] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager1[Xyflux.Frontend.Data.ApplicationUser]': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IUserStore1[Xyflux.Frontend.Data.ApplicationUser]' while attempting to activate 'Microsoft.AspNetCore.Identity.UserManager1[Xyflux.Frontend.Data.ApplicationUser]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.SignInManager1[Xyflux.Frontend.Data.ApplicationUser] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.SignInManager1[Xyflux.Frontend.Data.ApplicationUser]': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IUserStore1[Xyflux.Frontend.Data.ApplicationUser]' while attempting to activate 'Microsoft.AspNetCore.Identity.UserManager1[Xyflux.Frontend.Data.ApplicationUser]'.) (Error while validating the service descriptor 'ServiceType: Xyflux.Frontend.Components.Account.IdentityUserAccessor Lifetime: Scoped ImplementationType: Xyflux.Frontend.Components.Account.IdentityUserAccessor': Unable to resolve service for type 'Microsoft.AspNetCore.Identity.IUserStore1[Xyflux.Frontend.Data.ApplicationUser]' while attempting to activate 'Microsoft.AspNetCore.Identity.UserManager1[Xyflux.Frontend.Data.ApplicationUser]'.)'

And full DI

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Xyflux.Frontend.Components;
using Xyflux.Frontend.Components.Account;
using Xyflux.Frontend.Data;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents()
    .AddInteractiveWebAssemblyComponents();

builder.Services.AddCascadingAuthenticationState();
builder.Services.AddScoped<UserManager<ApplicationUser>>();
builder.Services.AddScoped<SignInManager<ApplicationUser>>();
builder.Services.AddScoped<IdentityUserAccessor>();
builder.Services.AddScoped<IdentityRedirectManager>();
builder.Services.AddScoped<AuthenticationStateProvider, PersistingRevalidatingAuthenticationStateProvider>();


builder.Services.AddBff();

builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
    options.Cookie.Name = "BlazorApp.Cookie";
    options.Cookie.HttpOnly = true;
    options.SlidingExpiration = true;
    options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
})
.AddOpenIdConnect("oidc", options =>
{
    options.Authority = "https://localhost:5001"; 
    options.ClientId = "blazor-client"; 
    options.ClientSecret = "your_client_secret"; 
    options.ResponseType = "code";
    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("api1");
    options.SaveTokens = true; 
    options.GetClaimsFromUserInfoEndpoint = true;
    options.ForwardSignIn = "";
    
});

builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = options.DefaultPolicy;
});

builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseWebAssemblyDebugging();
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseAuthentication();
app.UseAuthorization();

app.UseStaticFiles();
app.UseAntifery();

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode()
    .AddInteractiveWebAssemblyRenderMode()
    .AddAdditionalAssemblies(typeof(Xyflux.Frontend.Client._Imports).Assembly);

// Add additional endpoints required by the Identity /Account Razor components.
app.MapAdditionalIdentityEndpoints();

app.Run();

I'm also using the duende.bff framework.

Can somebody guide me what I did wrong and guide me what my next steps to do are?

Share Improve this question edited Feb 26 at 1:24 Ruikai Feng 11.9k1 gold badge7 silver badges16 bronze badges asked Feb 24 at 17:52 Technology ResearcherTechnology Researcher 5552 gold badges7 silver badges21 bronze badges 4
  • Username and password is not recommend since the password is not encrypted. Instead a credential should be used where the password is encrypted. You could use Anonymous Authentication(see : learn.microsoft/en-us/iis/configuration/system.webserver/…). Usually you let the login of the user get passed from the frontend to the backend with using the users credentials. – jdweng Commented Feb 24 at 18:54
  • depends you definitly use pkce, but i assume i'll request a jwt token, and need to implement a revocation list and other security measures – Technology Researcher Commented Feb 24 at 19:24
  • See enumeration on line 43 for GrantTypes : github/DuendeSoftware/Samples/blob/main/IdentityServer/v7/… You can set granttype to password. See docs.duendesoftware/identityserver/v7/tokens/password_grant – jdweng Commented Feb 24 at 22:15
  • @jdweng oh thank you this is very usefull to me, any idea tough why my frontend is failing, i feel like i'm missing something despite how i need to implement it. – Technology Researcher Commented Feb 25 at 9:28
Add a comment  | 

1 Answer 1

Reset to default 0

The error indicates you didn't register DB related services,try add required services follow this document:

builder.Services.AddIdentityServer()
        .AddConfigurationStore(options =>
        {
            options.ConfigureDbContext = b => b.UseSqlite(connectionString,
                sql => sql.MigrationsAssembly(migrationsAssembly));
        })
        .AddOperationalStore(options =>
        {
            options.ConfigureDbContext = b => b.UseSqlite(connectionString,
                sql => sql.MigrationsAssembly(migrationsAssembly));
        })
        .AddTestUsers(TestUsers.Users);

If you are using ASP.NET Core Identity ,try register services follow this document:

builder.Services
    .AddIdentityServer(options =>
    {
        // ...
    })
    .AddInMemoryIdentityResources(Config.IdentityResources)
    .AddInMemoryApiScopes(Config.ApiScopes)
    .AddInMemoryClients(Config.Clients)
    .AddAspNetIdentity<ApplicationUser>()
    .AddProfileService<CustomProfileService>();

本文标签: cStuck on authenticationauthorization setupStack Overflow