I have a Blazor WebAssembly app using IdentityServer that comes with the template as my authentication service. I am having an issue where some users are seeing "There was an error trying to log you in: ''" once they try to login. I had users clear cookies and cache, and they are still experiencing this problem in all their browsers. The weird thing is that most users are able to login, but only a small percent is getting that error. Another odd thing is that it seems like if they use another device such as a phone, another pc, or ipad it works. What could be causing this issue? I have been having trouble trying to debug this issue as I am not able to replicate it on my end and so far not seeing any logs to get any info.
This app is hosted in Google Cloud Platform using linux Docker container.
Thank you in advance
Edit: Here is my startup class
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
private const string XForwardedPathBase = "X-Forwarded-PathBase";
private const string XForwardedProto = "X-Forwarded-Proto";
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins("https://www.fakedomainexample.com",
"https://fakedomainexample.com");
});
});
services.AddHttpContextAccessor();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseMySql(
Configuration.GetConnectionString("ConnectionString")));
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
// For some reason, I need to explicitly assign the IssuerUri or else site gets invalid_issuer error
services.AddIdentityServer(x => x.IssuerUri = "https://www.fakedomainexample.com").AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options => {
options.IdentityResources["openid"].UserClaims.Add("name");
options.ApiResources.Single().UserClaims.Add("name");
options.IdentityResources["openid"].UserClaims.Add("role");
options.ApiResources.Single().UserClaims.Add("role");
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("role");
services.Configure<IdentityOptions>(options =>
{
// Password settings.
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequiredLength = 8;
options.Password.RequiredUniqueChars = 1;
// User settings.
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
options.User.RequireUniqueEmail = true;
options.SignIn.RequireConfirmedAccount = false;
});
// Added Cookie options below to fix an issue with login redirect in Chrome for http
// https://stackoverflow.com/questions/60757016/identity-server-4-post-login-redirect-not-working-in-chrome-only
// This one worked: https://stackoverflow.com/questions/63449387/cannot-redirect-back-to-angular-client-after-login-in-identity-server
services.ConfigureExternalCookie(option =>
{
option.LoginPath = "/Account/Login";
option.Cookie.IsEssential = true;
option.Cookie.SameSite = SameSiteMode.Lax;
});
services.ConfigureApplicationCookie(option =>
{
option.LoginPath = "/Account/Login";
option.Cookie.IsEssential = true;
option.Cookie.SameSite = SameSiteMode.Lax;
});
services.AddAuthentication()
.AddIdentityServerJwt();
services.AddControllersWithViews();
services.AddRazorPages();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
app.UseRewriter(new RewriteOptions()
.AddRedirectToWwwPermanent());
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseWebAssemblyDebugging();
}
else
{
app.UseExceptionHandler("/Error");
// 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.Use((context, next) =>
{
if (context.Request.Headers.TryGetValue(XForwardedPathBase, out StringValues pathBase))
{
context.Request.PathBase = new PathString(pathBase);
}
if (context.Request.Headers.TryGetValue(XForwardedProto, out StringValues proto))
{
context.Request.Scheme = proto;
}
//context.SetIdentityServerOrigin("https://www.fakedomainexample.com");
return next();
});
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();
const string cacheMaxAge = "3600";
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
ctx.Context.Response.Headers.Add("Cache-Control", $"public, max-age={cacheMaxAge}");
}
});
app.UseCookiePolicy(new CookiePolicyOptions
{
MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.Lax,
});
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseIdentityServer();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapFallbackToFile("index.html");
});
}
}
There is an option available to enable authentication for the Blazor app when you create the application. To enable authentication for Blazor server app, click on “Change” under “Authentication section and select “Individual User Accounts” option and then click on “Ok” button when you create a new Blazor server app.
When an error occurs, Blazor apps display a light yellow bar at the bottom of the screen: During development, the bar directs you to the browser console, where you can see the exception. In production, the bar notifies the user that an error has occurred and recommends refreshing the browser.
Blazor Server authentication Blazor Server apps operate over a real-time connection that's created using SignalR. Authentication in SignalR-based apps is handled when the connection is established. Authentication can be based on a cookie or some other bearer token.
Your Blazor WASM application will run fine on Chrome, Edge, Firefox, Safari and also on the mobile variants of these.
Blazor uses the existing ASP.NET Core authentication mechanisms to establish the user's identity. The exact mechanism depends on how the Blazor app is hosted, Blazor WebAssembly or Blazor Server. In Blazor WebAssembly apps, authentication checks can be bypassed because all client-side code can be modified by users.
Blazor WebAssembly Security Overview Blazor WebAssembly is a single page application (SPA) and, we can integrate different authorization options inside it. The most common option is using the tokens with OAuth2 and OIDC. As the most common option, we are going to use it in this series as well.
So basically, after we log in with our Blazor WebAssembly application, the IdentityServer will provide us with id and access tokens. We are going to use the id token for the user’s information and the access token to access our Web API’s protected resources.
ASP.NET Core supports the configuration and management of security in Blazor apps. Security scenarios differ between Blazor Server and Blazor WebAssembly apps. Because Blazor Server apps run on the server, authorization checks are able to determine: The UI options presented to a user (for example, which menu entries are available to a user).
We also faced this problem. The error appears if the server time does not match the client time. Experiments have shown that it is enough to have a difference of 10 minutes. Ideally, the time on the client and server should be in sync. We are currently asking customers to check the time on the device, but this is not a solution to the problem.
Who have this problem when publishing on IIS with a self-signed certificate, it may be caused by auth of Application Pool on read the Certificate.
For solve this problem, open certification manager, right click on the certificate, all tasks, private key manager and insert IIS group (IIS_IUSRS) for read/write permission. For test, try "Everyone".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With