I have followed the Deblokt tutorial here which explains in great detail how to set up IdentityServer4 in .net core 3.1 and use AspNetCore Identity for the user store.
I can log in to my IdentityServer from the https://localhost:5001/Account/Login url (and logout) just fine... But I cannot access the AspNet Core Identity pages (eg Register/ForgotPassword/AccessDenied etc). I have scaffolded them out, so they sit under Areas/Identity/Pages/Account... but when I navigate to them, eg https://localhost:5001/Identity/Account/Register, I just get a 404 not found.
I'm not sure, but suspect this could be a routing issue, so I have researched providing routing for these pages, but the examples I have seen for IdentityServer are for Core2.1 and use the app.UseMVC ... which my startup does not have. I have tried to include it, but I get error saying
Endpoint Routing does not support 'IApplicationBuilder.UseMvc(...)'. To use 'IApplicationBuilder.UseMvc' set 'MvcOptions.EnableEndpointRouting = false' inside 'ConfigureServices(...)'
So where do I go from here?
I downloaded the tutorials accompanying solution from GitHub, but it is a Core 2.1 solution, so suspect the tutorial is a rewrite/upgraded version to 3.1.
This is my Startup file...
public class Startup
{
public IWebHostEnvironment Environment { get; }
public IConfiguration Configuration { get; }
public Startup(IWebHostEnvironment environment, IConfiguration configuration)
{
Environment = environment;
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
// uncomment, if you want to add an MVC-based UI
services.AddControllersWithViews();
services.AddRazorPages(); // I recently added this, but made no difference
string connectionString = Configuration.GetConnectionString("DefaultConnection");
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddDbContext<IdentityDbContext>(options =>
options.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly))
);
services.AddDbContext<Data.ConfigurationDbContext>(options => options.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly)));
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.SignIn.RequireConfirmedEmail = true;
})
.AddEntityFrameworkStores<IdentityDbContext>()
.AddDefaultTokenProviders();
var builder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
options.UserInteraction.LoginUrl = "/Account/Login";
options.UserInteraction.LogoutUrl = "/Account/Logout";
options.Authentication = new AuthenticationOptions()
{
CookieLifetime = TimeSpan.FromHours(10), // ID server cookie timeout set to 10 hours
CookieSlidingExpiration = true
};
})
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = b => b.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly));
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = b => b.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly));
options.EnableTokenCleanup = true;
})
.AddAspNetIdentity<ApplicationUser>();
X509Certificate2 cert = null;
using (X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
certStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = certStore.Certificates.Find(
X509FindType.FindByThumbprint,
// Replace below with your cert's thumbprint
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" // Replaced for this post
,
false);
// Get the first cert with the thumbprint
if (certCollection.Count > 0)
{
cert = certCollection[0];
}
}
// Fallback to local file for development
if (cert == null)
{
cert = new X509Certificate2(Path.Combine(Environment.ContentRootPath, "xxxxxxxxx.pfx"), "xxxxxxxxxxxxxxxxxxxxx"); // Replaced for this post
}
// not recommended for production - you need to store your key material somewhere secure
//builder.AddDeveloperSigningCredential();
builder.AddSigningCredential(cert);
builder.AddValidationKey(cert);
services.AddScoped<IProfileService, ProfileService>();
}
public void Configure(IApplicationBuilder app)
{
if (Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// uncomment if you want to add MVC
app.UseStaticFiles();
app.UseRouting();
app.UseIdentityServer();
// uncomment, if you want to add MVC
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
}
}
ASP.NET Core Identity: Is an API that supports user interface (UI) login functionality. Manages users, passwords, profile data, roles, claims, tokens, email confirmation, and more.
About IdentityServer4IdentityServer is a free, open source OpenID Connect and OAuth 2.0 framework for ASP.NET Core.
IdentityServer is an authentication server that implements OpenID Connect (OIDC) and OAuth 2.0 standards for ASP.NET Core. It's designed to provide a common way to authenticate requests to all of your applications, whether they're web, native, mobile, or API endpoints.
ASP.NET Identity is Microsoft's user management library for ASP.NET. It includes functionality such as password hashing, password validation, user storage, and claims management. It usually also comes with some basic authentication, bringing its own cookies and multi-factor authentication to the party.
Well, it was 1 line of code in my startup.cs file
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapRazorPages(); // This one!
});
Oh and another error occurred on the register page if anyone comes across it.
Unable to resolve service for type 'Microsoft.AspNetCore.Identity.UI.Services.IEmailSender'
just add the following line of code to the end of your ConfigureServices method in Startup.cs
services.AddTransient<IEmailSender,SomeEmailSender>();
The IEmailSender is from Microsoft.AspNetCore.Identity.UI.Services. Just create a class that implements this interface and declare it here.
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