I have a problem with Forms authentication in asp net core, the fact is that when the page loads, I do not see a redirect to my login URL "/Home/Login" (it s correct). Nothing is happend. Here is the code for my Startup.cs
public void ConfigureServices(IServiceCollection services)
{
string connection = Configuration.GetConnectionString("DefaultConnection");
services.AddDbContext<EventSchedulerEntities>(options =>
options.UseSqlServer(connection));
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.SlidingExpiration = true;
options.LoginPath = $"/Home/Login";
options.Cookie.IsEssential = true;
});
services.AddAuthorization();
services.AddControllersWithViews();
}
public void Configure(IApplicationBuilder app)
{
app.UseDeveloperExceptionPage();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"
);
});
}
If anyone knows why this is happening, please help.
Controller code:
[Authorize]
public IActionResult Index()
{
return View();
}
[AllowAnonymous]
public IActionResult Login(string ReturnUrl)
{
return View();
}
Cookie, was clear before start.
Related
We have an existing .NET 5.0 Blazor web application. I have added an ASP.NET Core Web API to the same project because I want to provide a REST interface to external consumers. When I request http://localhost:5000/stripe/customerwebhook, I get a 404 not found error. What could I be missing?
My CustomerWebhookController API class looks like the following:
[Route("stripe/[controller]")]
[ApiController]
public class CustomerWebhookController : ControllerBase
{
[HttpPost]
public async Task<IActionResult> Index()
{
return Ok();
}
}
Startup.cs:
using Microsoft.AspNetCore.Mvc;
public partial class Startup
{
public void ConfigureServices(IServiceCollection services)
{
OnConfiguringServices(services);
services.AddHttpContextAccessor();
services.AddScoped<HttpClient>(serviceProvider =>
{
var uriHelper = serviceProvider.GetRequiredService<NavigationManager>();
return new HttpClient
{
BaseAddress = new Uri(uriHelper.BaseUri)
};
});
services.AddHttpClient();
services.AddAuthentication();
services.AddAuthorization();
services.AddControllersWithViews();
services.AddMvc(options => options.EnableEndpointRouting = false)
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
services.AddRazorPages();
services.AddServerSideBlazor().AddHubOptions(o =>
{
o.MaximumReceiveMessageSize = 10 * 1024 * 1024;
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ApplicationIdentityDbContext identityDbContext)
{
OnConfiguring(app, env);
if (env.IsDevelopment())
{
Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
app.UseDeveloperExceptionPage();
}
else
{
app.Use((ctx, next) =>
{
return next();
});
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseMvcWithDefaultRoute();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}
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 ??
I am using this middleware as the concepts are new to me
https://github.com/blowdart/idunno.Authentication/tree/master/src/idunno.Authentication.Basic
I've implemented startup exactly as it says
However, every time I post to the WeatherForecast end point I get a 404 if the [Authorize] identifier is there. I did some reading and hence added the AuthenticationSchemes but same result
It cannot be a missing redirect, which is the other problem, as the controller is just returning content in that page?
Please can someone point me in the right direction?
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddMvc();
services.AddRazorPages();
services.AddControllersWithViews();
services.AddAuthentication(BasicAuthenticationDefaults.AuthenticationScheme)
.AddBasic(options =>
{
//options.Realm = "idunno";
options.Events = new BasicAuthenticationEvents
{
OnValidateCredentials = context =>
{
if (context.Username == context.Password)
{
var claims = new[]
{
new Claim(
ClaimTypes.NameIdentifier,
context.Username,
ClaimValueTypes.String,
context.Options.ClaimsIssuer),
new Claim(
ClaimTypes.Name,
context.Username,
ClaimValueTypes.String,
context.Options.ClaimsIssuer)
};
context.Principal = new ClaimsPrincipal(
new ClaimsIdentity(claims, context.Scheme.Name));
context.Success();
}
return Task.CompletedTask;
}
};
});
}
Then this
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.UseAuthentication();
app.UseAuthorization();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
Controller looks like this:
[Route("[controller]")]
[Authorize(AuthenticationSchemes = idunno.Authentication.Basic.BasicAuthenticationDefaults.AuthenticationScheme)]
public class WeatherForecastController : ControllerBase
{
[HttpGet]
public ActionController<WeatherForecast> Get()
{
return Content("Authorised");
}
}
As per comment, some of the commands were in the wrong order
I'm using ASP.NET Core 2.1 with the new Identity framwork from .NET. The regular Authorization attribute works as long as no role specific role is requested.
Do I need some extending / customized policies to use roles? Below is a minimized sample of my code:
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
// Does not change anything
// services.AddAuthorization();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
HomeController.cs
public async Task<IActionResult> Index()
{
if (!await _roleManager.RoleExistsAsync("Admin"))
{
await _roleManager.CreateAsync(new IdentityRole("Admin"));
}
var user = await _userManager.FindByEmailAsync("danny.meier#tpcag.ch");
if (!await _userManager.IsInRoleAsync(user, "Admin"))
{
await _userManager.AddToRoleAsync(user, "Admin");
await _userManager.UpdateAsync(user);
}
return View();
}
[Authorize]
public IActionResult About()
{
ViewData["Message"] = "Your application description page.";
return View();
}
[Authorize(Roles = "Admin")]
public IActionResult Contact()
{
ViewData["Message"] = "Your contact page.";
return View();
}
It's a known issue in the version of 2.1 and has been fixed in 2.2 preview-1 .
The reason is that the new method of AddDefaultIdentity<TUser>() , which is introduced in ASP.NET Core 2.1 , will not make Roles enabled by default .
To walk around it , instead of using the new AddDefaultIdentity<TUser>() to configure Identity , simply use the old-style api :
services.AddIdentity<AppUser, IdentityRole>()
.AddRoleManager<RoleManager<IdentityRole>>()
.AddDefaultUI()
.AddDefaultTokenProviders()
.AddEntityFrameworkStores<ApplicationDbContext>();
Also , if you have already signed someone in before , please do logout first and login again , it will work as expected now .
[Edit] For ASP.NET Core 3.1, invoke .AddRoles<IdentityRole>():
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<AppIdentityDbContext>();
And then logout and login again.
Hmmm. I have the following code in an Asp.Net 2.1 project that is working:
services.AddDefaultIdentity<IdentityUser>()
.AddRoles<IdentityRole>()
//.AddDefaultUI(UIFramework.Bootstrap4)
.AddDefaultTokenProviders()
.AddEntityFrameworkStores<ApplicationDbContext>();
I am trying to configure cookie authentication with identity and ef. So far I am able to have a valid Set-Cookie in my Controller response. The browser sends this cookie back, but the AuthorizeFilter always redirects to Login page, thus Authentication doesn't seem to work. What am I suppoed to configure?
Here's my ConfigureServices in Startup so far:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddCors(o => o.AddPolicy("Cors", builder =>
{
builder.WithOrigins(Configuration["AllowedOrigins"].Split(","))
.AllowAnyMethod()
.AllowCredentials()
.AllowAnyHeader();
}));
services.AddDbContext<MyIdentityDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<MyIdentityDbContext>()
.AddDefaultTokenProviders();
services.ConfigureApplicationCookie(options => {
if (!String.IsNullOrEmpty(Configuration["AuthCookieDomain"]))
{
options.Cookie.Domain = Configuration["AuthCookieDomain"];
}
options.Cookie.Name = Configuration["AuthCookieName"];
options.Cookie.HttpOnly = false;
options.Cookie.SameSite = SameSiteMode.None;
});
}
Then, my Configure in Startup:
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
IServiceProvider serviceProvider)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors("Cors");
app.UseMvc();
app.UseAuthentication();
}
Then, my Action that actually successfully sets the cookie
// GET api/values
[HttpPost]
public async Task<ActionResult> Post([FromBody] AuthPost post)
{
if (post == null || String.IsNullOrEmpty(post.UserName) || String.IsNullOrEmpty(post.Password))
{
return BadRequest();
}
var result = await signInManager.PasswordSignInAsync(post.UserName, post.Password, true, false);
if (result.Succeeded)
{
return Ok();
}
return Unauthorized();
}
And finally, my other Action with Authorize attribute that does not work (Always redirects to Login)
[HttpGet]
[Authorize]
public async Task<ActionResult> Get()
{
var user = await userManager.GetUserAsync(User);
return Ok(new { UserName = user.UserName });
}
OK, ConfigureApplicationCookie is the way to work. What caused the issue was the WRONG order of app.UseMvc(); and app.UseAuthentication();
app.UseAuthentication() must be invoked before app.UseMvc()!