Account/Login not found - identity - asp.net-core

I am putting identity in my already created project, but it is not locating the Account/Login page.
It is not localizing the page, this is the controller:
[Route("[controller]/[action]")]
public class AccountController : Controller
{
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly ILogger _logger;
public readonly Erp.Models.ErpDb _context;
public AccountController(Erp.Models.ErpDb context, SignInManager<ApplicationUser> signInManager, ILogger<AccountController> logger)
{
_signInManager = signInManager;
_logger = logger;
_context = context;
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout()
{
await _signInManager.SignOutAsync();
_logger.LogInformation("User logged out.");
return RedirectToPage("/Index");
}
}
Startup
public class Startup
{
private IHostingEnvironment env;
private IConfigurationRoot config;
public Startup(IHostingEnvironment env)
{
this.env = env;
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
config = builder.Build();
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ErpDb>(options => options.UseSqlServer("Data Source =servidor; Initial Catalog = ERP; User ID = sa; Password = password;Connect Timeout=30;"));
services.AddMvc();
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ErpDb>()
.AddDefaultTokenProviders();
if (env.IsDevelopment())
services.AddScoped<IMailService, DebugMailService>();
else
services.AddScoped<IMailService, MailService>();
services.AddMvc().AddJsonOptions(jsonOptions =>
{
jsonOptions.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
jsonOptions.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
})
.AddRazorPagesOptions(options =>
{
options.Conventions.AuthorizeFolder("/Account/Manage");
options.Conventions.AuthorizePage("/Account/Logout");
options.Conventions.AuthorizePage("/Details");
});
services.AddCors();
services.AddDistributedMemoryCache();
services.AddSession();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(config.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseAuthentication();
app.UseSession();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=About}/{id?}");
});
}

Just Change Code :
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
change to :
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});

Since you are using Razor pages for your account UI, you cannot have those .cshtml files inside the Views folder. The Views folder is only meant for views used by MVC but not Razor Pages.
In order to have the framework pick those up with the correct URL, you need to move them to the Pages directory instead.
Since you are then mixing Razor Pages and MVC in the same project (which is not a problem), you will have to adjust your layout setup in order to have both pick up the same layout file.
Basically, you need to make sure that you have a _ViewStart.chtml file in both the Views and the Pages folder that configure the layout to use. If you previously used MVC, then you likely already have a Views/_ViewStart.cshtml. In that case, you need to also create a Pages/_ViewStart.cshtml file (you can copy it). The file should look like this:
#{
Layout = "_Layout";
}
Then, Razor Pages will also attempt to pick up the layout at Views/Shared/_Layout.cshtml, just like MVC does.

Related

.net core 5.0.2 and jwt => response 401 Unauthorized

I am following an video tutorial for identity server 4 with web api's.
And Im not sure when I went wrong.
Im getting 401 Unauthorized when I try to call api with bearer token.
In previos step, without authorization, my api worked.
This is my api controller in my TablesReach.API project:
...
namespace TablesReach.Controllers
{
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase
{
private readonly DataContext _context;
public UsersController(DataContext context)
{
_context = context;
}
// GET: api/Users
[HttpGet]
public async Task<ActionResult<IEnumerable<User>>> GetUsers()
{
return await _context.Users.ToListAsync();
}
...
this is my Startup.cs of my api project:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(opts =>
{
opts.Authority = "http://localhost:5000";
opts.RequireHttpsMetadata = false;
opts.ApiName = "TablesReachApi";
});
services.AddDbContext<DataContext>(opts => opts.UseInMemoryDatabase("UNWDb"));
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseAuthentication();
}
}
My other project TablesReach.IdentityServer is host on localhost:5000
and Im being able to get bearer token, so I assume that this project is quite OK.
identityServer startup.cs class:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiScopes(Config.GetAllApiResources())
.AddInMemoryClients(Config.GetClients());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
//else
//{
// app.UseExceptionHandler("/Home/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.UseHttpsRedirection();
//app.UseStaticFiles();
//app.UseRouting();
//app.UseAuthorization();
//app.UseEndpoints(endpoints =>
//{
// endpoints.MapControllerRoute(
// name: "default",
// pattern: "{controller=Home}/{action=Index}/{id?}");
//});
app.UseIdentityServer();
}
}
and Config.cs:
public class Config
{
public static IEnumerable<ApiScope> GetAllApiResources()
{
return new List<ApiScope>
{
new ApiScope("TablesReachApi", "Api for solution")
};
}
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "client",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "TablesReachApi" }
}
};
}
}
Note: When I remove annotation [Authorize] from my api controller I can reach my method.
For some middleware, order matters. Authentication and authorization, for example, can't go in the order that you have put them in the API. Microsoft has some clear documentation on this for you to read here..

error 404 showing for each controller after user authorization via ldap

Scenario:
I'm implementing asp.net core 3.1 MVC project. I authorize my user via ldap Active Directory service. The user authenticates successfully and enter into my website. but after clicking on each menu item in order to see the related controller index it shows white page. I wrote on top of all my controller class [Authorize] keyword in order to let any authorized user to see all controllers.
My Problem is:
when user clicks on each menu item in home in order to see the related controller's index, it shows white page and when I publish my project on ldap server, it shows me 404 error. I appreciate if any one can suggest me a solution. It seems to the routing has problem but I'm not sure. I even wrote on top of my controller class the keyword [AllowAnonymous] but still I see white pages for index pages for each controller. Should I add anything to startup.cs for AutheticationHelper or CustomAuthenticationMiddleware as a service?
Here is my sign in method in account controller
namespace CSDDashboard.Controllers
{
[Route("[controller]/[action]")]
[AllowAnonymous]
public class AccountController : Controller
{
private readonly LdapUserManager _userManager;
private readonly LdapSignInManager _signInManager;
private readonly ILogger _logger;
public AccountController(
LdapUserManager userManager,
LdapSignInManager signInManager,
ILogger<AccountController> logger)
{
this._userManager = userManager;
this._signInManager = signInManager;
this._logger = logger;
}
[AllowAnonymous]
[HttpGet]
public async Task<IActionResult> Signin(string returnUrl = null)
{
// Clear the existing external cookie to ensure a clean login process
await this.HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
this.ViewData["ReturnUrl"] = returnUrl;
return this.View();
}
[AllowAnonymous]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Signin(SigninViewModel model, string returnUrl = null)
{
this.ViewData["ReturnUrl"] = returnUrl;
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "tehran.iri"))
{
// validate the user's credentials
//var result = ctx.ValidateCredentials(model.UserName, model.Password);
// try {
if (ctx.ValidateCredentials(model.UserName, model.Password))
{
// credentials are OK --> allow user in
HttpContext.Session.MarkAsAuthenticated(model.UserName);
//Added recently
Debug.Writeline(string.Format("Redirection to {0}", returnUrl);
return RedirectToLocal(returnUrl);
}
else
{
this.TempData["ErrorMessage"] = "The username and/or password are incorrect!";
return this.View(model);
// credentials aren't OK --> send back error message
}
}
}}}
Here is my middleware class and AuthenticationHelper class
public static class AuthenticationHelper
{
private const string SessionKey = "AuthenticationHelper.UserName";
public static void MarkAsAuthenticated(this Microsoft.AspNetCore.Http.ISession session, string authenticatedUserName)
{
session.SetString(SessionKey, authenticatedUserName);
}
public static ClaimsPrincipal GetAuthenticatedUser(this Microsoft.AspNetCore.Http.ISession session)
{
string authenticatedUserName = session.GetString(SessionKey);
if (string.IsNullOrEmpty(authenticatedUserName)) return null;
return new GenericPrincipal(new GenericIdentity(authenticatedUserName), Array.Empty<string>());
}
}
public class CustomAuthenticationMiddleware
{
private readonly RequestDelegate _next;
public CustomAuthenticationMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
ClaimsPrincipal user = context.Session.GetAuthenticatedUser();
if (user != null) context.User = user;
await _next(context);
}
}
public static class CustomAuthenticationMiddlewareExtensions
{
public static IApplicationBuilder UseCustomAuthentication(this IApplicationBuilder builder)
{
return builder.UseMiddleware<CustomAuthenticationMiddleware>();
}
}
Here is my code in statrup.cs:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<LdapSettings>(Configuration.GetSection("LdapSettings"));
services.AddDbContext<LdapDbContext>(options =>
options.UseSqlite(
Configuration.GetConnectionString("CSDDashboardContext")));
//-------------------------------------------------
services.AddIdentity<LdapUser, IdentityRole>()
.AddEntityFrameworkStores<LdapDbContext>()
.AddUserManager<LdapUserManager>()
.AddSignInManager<LdapSignInManager>()
.AddDefaultTokenProviders();
services.ConfigureApplicationCookie(options =>
{
options.Cookie.Name = "CSDDashboard";
options.LoginPath = "/Account/Signin"; // If the LoginPath is not set here, ASP.NET Core will default to /Account/Login
options.LogoutPath = "/Account/Signout"; // If the LogoutPath is not set here, ASP.NET Core will default to /Account/Logout
options.AccessDeniedPath = "/Account/AccessDenied"; // If the AccessDeniedPath is not set here, ASP.NET Core will default to /Account/AccessDenied
options.SlidingExpiration = true;
options.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
});
services.AddRazorPages();
services.AddTransient<ILdapService, LdapService>();
//-------------------------------------------------
services.AddControllersWithViews();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30);//We set Time here
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
services.AddDistributedMemoryCache();
//Notice this is NOT the same class... Assuming this is a valid DBContext. You need to add this class as well.
services.AddDbContext<CSSDDashboardContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("CSDDashboardContext")));
services.AddDbContext<CSDDashboardContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("CSDDashboardContext")));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// app.UseDeveloperExceptionPage(options);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/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.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSession();
app.UseRouting();
app.UseCustomAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
//Here are all of my controllers, but as it seems just I can uncomment one controller pattern here, I commented all the others
// pattern: "{controller=Applications}/{action=Index}/{id?}");
//pattern: "{controller=Home}/{action=Index}/{id?}");
// pattern: "{controller=ApiApplications}/{action=Index}/{id?}");
pattern: "{controller=Gates}/{action=Index}/{id?}");

Policy base authorization asp.net core 3.1

I want to authorize users in asp.net core 3.1 for example users that have admin role and CanDoSomething claim.
I Remove AddDefaultIdentity and add pages that i need with scaffolding
ApplicationClaimsPrincipalFactory :
public class ApplicationClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser>
{
public ApplicationClaimsPrincipalFactory(
UserManager<ApplicationUser> userManager,
IOptions<IdentityOptions> optionsAccessor) : base(userManager, optionsAccessor)
{ }
public override async Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
{
var principal = await base.CreateAsync(user);
if (user.CanDoSomething) //it's true
{
((ClaimsIdentity)principal.Identity)
.AddClaim(new Claim("CanDoSomething", "true"));
}
return principal;
}
}
ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddControllersWithViews();
services.AddRazorPages();
services.AddMvc();
services.AddAuthorization(options =>
{
options.AddPolicy("superadmin", policy =>
policy
.RequireRole("admin")
.RequireClaim("CanDoSomething", "true"));
});
services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, ApplicationClaimsPrincipalFactory>();
}
Configure:
public void Configure(
IApplicationBuilder app,
IWebHostEnvironment env,
UserManager<ApplicationUser> userManager,
RoleManager<IdentityRole> roleManager)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/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.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
ApplicationDbInitializer.Seed(userManager, roleManager);//Role created and users add to role successfully
}
ApplicationDbInitializer:
public static class ApplicationDbInitializer
{
public static void Seed(
UserManager<ApplicationUser> userManager,
RoleManager<IdentityRole> roleManager)
{
var roleName = "admin";
var pw = "#Vv123456";
roleManager.CreateAsync(new IdentityRole
{
Name = roleName,
NormalizedName = roleName.ToUpper()
}).Wait();
if (userManager.FindByEmailAsync("b#b.com").Result == null)
{
var user = new ApplicationUser
{
UserName = "b#b.com",
Email = "b#b.com",
CanDoSomething = true
};
if (userManager.CreateAsync(user, pw).Result.Succeeded)
userManager.AddToRoleAsync(user, roleName).Wait();
}
}
}
Use it like this:
[Authorize(Policy = "superadmin")]
public IActionResult Index()
{
return View();
}
When i login it redirect me to access denied page
I am doing it right? if yes What should i do now?
I make some change and it worked but i dont know why
Remove ApplicationClaimsPrincipalFactory and add claim in Seed with AddClaimAsync
In the first way when i check the db and table AspNetUserClaims there is no any CanDoSomething claim but i write this and problem solved:
userManager.AddClaimAsync(user, new Claim(CanDoSomething, "true")).Wait();
Why ApplicationClaimsPrincipalFactory not worked ??

How to configure dotnetcore 3 site to return 401 with custom authorization filter rather than redirecting to AccessDenied page

I've got a site using the new dotnetcore3 angular template. I've created a custom authorization filter that's currently extremely simple
public class ClaimRequirementFilter : IAuthorizationFilter
{
readonly string _claim;
public ClaimRequirementFilter(string claim)
{
_claim = claim;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
if (_claim != "test")
{
context.Result = new ForbidResult();
}
}
}
public class ClaimRequirementAttribute : TypeFilterAttribute
{
public ClaimRequirementAttribute(string claimType) : base(typeof(ClaimRequirementFilter))
{
Arguments = new object[] {claimType };
}
}
[Route("{jobId}")]
[ClaimRequirement("testfail")]
[HttpGet]
public async Task<IActionResult> GetJob([FromRoute] Guid jobId)
{
//stuff
{
However, whenever a request fails (which will be all of them right now), it 302s me to the AccessDenied page with a returnUrl of the URL I was trying to hit.
However, since this request is being made from my angular client, I would rather it just return a 401 (or 403 since in this case it's because the loggedin user doesn't have permission to do what they're trying to do), and I'm not sure how to configure it.
Per Ruard's request, here is my Startup configuration
public class Startup
{
public Startup(IWebHostEnvironment env, IConfiguration configuration)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddApplicationInsightsTelemetry();
services.AddDbContext<ApplicationDbContext>(
options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
);
services.AddTransient<EmailSender, EmailSender>();
services.AddScoped<IRazorViewToStringRenderer, RazorViewToStringRenderer>();
services.Configure<EmailServiceConfiguration>(Configuration.GetSection("EmailServiceConfiguration"));
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddDefaultTokenProviders()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer(options =>
{
options.UserInteraction.LoginUrl = "/auth/login";
options.UserInteraction.LogoutUrl = "/auth/logout";
})
//.AddDeveloperSigningCredential()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
services.AddAuthentication()
// .AddGoogle(options =>
// {
// IConfigurationSection googleAuthNSection = Configuration.GetSection("Authentication:Google");
// options.ClientId = googleAuthNSection["ClientId"];
// options.ClientSecret = googleAuthNSection["ClientSecret"];
// })
.AddIdentityServerJwt();
services.AddControllersWithViews().AddRazorRuntimeCompilation();
services.AddRazorPages(options =>
{
options.Conventions.AddAreaPageRoute("Identity", "/Identity/Account/Login", "/auth/login");
});
services.AddAuthorization(options =>
{
// options.AddPolicy("RequireAdmin", policy =>
// {
// policy.RequireRole("Admin");
// });
// options.AddPolicy("CreateInternalUsers", policy =>
// {
// // policy.RequireRole("Admin");
// policy.RequireClaim("CreatePPGUser");
// });
});
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ApplicationDbContext context, IServiceProvider services)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
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();
}
context.Database.Migrate();
app.UseHttpsRedirection();
app.UseStaticFiles();
if (!env.IsDevelopment())
{
app.UseSpaStaticFiles();
}
app.UseRouting();
app.UseAuthentication();
app.UseIdentityServer();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}"
);
endpoints.MapRazorPages();
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
// spa.UseAngularCliServer(npmScript: "start");
spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");
}
});
CreateUserRoles(services).Wait();
}
}
You should add a controller that serves as api. From the documentation:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
Methods from this controller will return the StatusCode instead of redirecting the user to a view.
Update
Based on your startup, it seems that you are not setting the CompatibilityVersion:
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
As documented, this is required in combination with ApiController:
The preceding change:
Is required to use the [ApiController] attribute at the controller level.
Opts in to potentially breaking behaviors introduced in ASP.NET Core 2.2.
In your case, assuming version 3.0:
services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
})
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

Adding super user with admin role in .net core framework

currently I'm trying to add a super User with Admin role in ASP.Net Core web app.
I want to add this user at startup, I spend some time researching about the subject without any success.
The sartup looks very standard and out of the box as follows
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
if (env.IsDevelopment())
{
// For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
builder.AddUserSecrets();
// This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
builder.AddApplicationInsightsSettings(developerMode: true);
}
builder.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddApplicationInsightsTelemetry(Configuration);
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseApplicationInsightsRequestTelemetry();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseApplicationInsightsExceptionTelemetry();
app.UseStaticFiles();
app.UseIdentity();
// Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
How this can be achieved?
Add parameter ApplicationDbContext dbContext into Configure method - dependency injection will create appropriate object and you can Find/Add required users:
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory, ApplicationDbContext dbContext)
{
...
if (dbContext.Users.Find(x => Name == "superadmin") == null)
{
db.Users.Add(new User { Name = "superadmin", ... });
db.SaveChanges();
}
}
Or you may add UserManager into parameters and use it for users manipulation.