Can you share your server's Startup.cs file? Specifically where you are registering/configuring the services for Identity/DbContexts. IdentityDbContext is basically the same as ApiAuthorizationDbContext but it adds the required DbSets for Persisted Grants and Device Flow Codes for enabling API-based authentication.
I have a working IdentityDbContext for both MVC Razor pages and Blazor WASM so I know it is possible! :) The difference being I implemented the types explicitly:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string,
IdentityUserClaim<string>, ApplicationUserRole, IdentityUserLogin<string>, IdentityRoleClaim<string>,
IdentityUserToken<string>>, IPersistedGrantDbContext
{
private readonly IOptions<OperationalStoreOptions> _operationalStoreOptions;
public ApplicationDbContext(DbContextOptions options, IOptions<OperationalStoreOptions> operationalStoreOptions) : base(options)
{
_operationalStoreOptions = operationalStoreOptions;
}
public DbSet<ApplicationUser> ApplicationUser { get; set; }
public DbSet<PersistedGrant> PersistedGrants { get; set; }
public DbSet<DeviceFlowCodes> DeviceFlowCodes { get; set; }
Task<int> IPersistedGrantDbContext.SaveChangesAsync() => base.SaveChangesAsync();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value);
// Override default AspNet Identity table names
modelBuilder.Entity<ApplicationUser>().Property(x => x.Created).HasDefaultValueSql("getdate()");
modelBuilder.Entity<ApplicationUser>(entity => { entity.ToTable(name: "Users"); });
modelBuilder.Entity<ApplicationRole>(entity => { entity.ToTable(name: "Roles"); });
modelBuilder.Entity<DeviceFlowCodes>(entity => { entity.ToTable("UserDeviceCodes"); });
modelBuilder.Entity<PersistedGrant>(entity => { entity.ToTable("UserPersistedGrants"); });
modelBuilder.Entity<ApplicationUserRole>(entity =>
{
entity.ToTable("UserRoles");
entity.HasKey(x => new { x.UserId, x.RoleId });
entity.HasOne(ur => ur.Role)
.WithMany(r => r.UserRoles)
.HasForeignKey(ur => ur.RoleId)
.IsRequired();
entity.HasOne(ur => ur.User)
.WithMany(r => r.UserRoles)
.HasForeignKey(ur => ur.UserId)
.IsRequired();
});
modelBuilder.Entity<IdentityUserClaim<string>>(entity => { entity.ToTable("UserClaims"); });
modelBuilder.Entity<IdentityUserLogin<string>>(entity => { entity.ToTable("UserLogins"); });
modelBuilder.Entity<IdentityUserToken<string>>(entity => { entity.ToTable("UserTokens"); });
modelBuilder.Entity<IdentityRoleClaim<string>>(entity => { entity.ToTable("RoleClaims"); });
}
}
In my Startup.cs file:
// ASP.NET Identity
services.AddDefaultIdentity<ApplicationUser>(options =>
{
options.User.RequireUniqueEmail = true;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
})
.AddRoles<ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
// Identity Server
var identityServerBuilder = services.AddIdentityServer(options =>
{
options.Authentication.CookieSlidingExpiration = true;
options.Authentication.CookieLifetime = TimeSpan.FromDays(7);
}).AddAspNetIdentity<ApplicationUser>()
.AddOperationalStore<ApplicationDbContext>()
.AddIdentityResources()
.AddApiResources()
.AddClients();