0
votes

When using ApiAuthorizationDbContext WASM Fetch page authenticates and passes the token, but Razor pages will not authenticate. When switching to IdentityDbContext, the opposite happens, I am able to authenticate the razor page but WASM fetch page will not authenticate. I have a very simple sample at https://github.com/williameduardo79/BlazorServerClientSample

This works well with Blazor WASM

 public class ApplicationDbContext : ApiAuthorizationDbContext<ApplicationUser>
    {
        public ApplicationDbContext(
            DbContextOptions options,
            IOptions<OperationalStoreOptions> operationalStoreOptions) : base(options, operationalStoreOptions)
        {
        }
    }

This works well with Blazor Pages

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
    }

How can I make it work?

Any references are appreciated :)

1
I too am facing the same issue. Did you end up working out how to solve this? - DotnetShadow

1 Answers

0
votes

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();