I'm working through the example provided here:
And I'm trying to implement something similar in my own app. Much of what the sample app does works, as replicated in my app, but there is one critical functionality that does not.
In this sample app, there is a "Contact (Authentication Required)" link, that when clicked loads the "/Contact" page - if the user is logged in.
If the user is not logged in, the "Contact (Authentication Required)" link still has its href= set to "/Contact", but when you click on it you end up in the "/Account/Login" controller, with ReturnUrl set to "/Contact".
The "Home" link directs to Index.cshtml, and does not redirect to /Account/Login " if the user is not logged in.
Which is all pretty ordinary, except ... I cannot find where the redirect to /Account/Login is configured, and I cannot determine why we're redirecting on one page but not the other.
What is it that causes Contact to redirect to Login and Home to not, and where do I configure that it's Account/Login that I want to redirect to?
Rakib's comment pointed me to a YouTube video, and an earlier video in the same series gave me a hint on one of my problems.
The sample app, in ConfigureServices(), has:
services.AddRazorPages(options =>
{
options.Conventions.AuthorizePage("/Contact");
});
So this is why "/Contact" requires authentication. But I still don't see what sets "/Account/Login" as the URL when you need authentication.
What is it that causes Contact to redirect to Login and Home to not?
[AllowAnonymous]
public class HomePage : PageModel
{
//...
}
[Authorize]
attribute or in startup.cs
it will redirect the user to the login page if he is not logged in.[Authorize]
public ContactModel : PageModel
{
// ...
}
Here is a sample configuration for authorization in startup, where we do create a role based policy named RequireAdmins
for a role name Admins
:
services.AddRazorPages()
.AddRazorPagesOptions(ops =>
{
ops.Conventions.AuthorizeAreaFolder("Panel", "/", "RequireAdmins");
ops.Conventions.AuthorizeFolder("/", "RequireAdmins");
ops.Conventions.AllowAnonymousToAreaPage("Identity", "/Account/AccessDenied");
});
services.AddAuthorization(ops =>
{
ops.AddPolicy("RequireAdmins", policy => policy.RequireRole("Admins"));
});
where do I configure that it's Account/Login that I want to redirect to?
The configuration can be done in startup, in general I do create a custom authentication cookie:
public class XCookieAuthEvents : CookieAuthenticationEvents
{
public override Task RedirectToLogin(RedirectContext<CookieAuthenticationOptions> context)
{
context.RedirectUri = $"/Identity/Account/CustomLogin";
return base.RedirectToLogin(context);
}
public override Task RedirectToLogout(RedirectContext<CookieAuthenticationOptions> context)
{
context.RedirectUri = $"/Identity/Account/CustomLogout";
return base.RedirectToLogout(context);
}
public override Task RedirectToAccessDenied(RedirectContext<CookieAuthenticationOptions> context)
{
context.RedirectUri = $"/Identity/Account/CustomAccessDenied";
return base.RedirectToAccessDenied(context);
}
public override Task RedirectToReturnUrl(RedirectContext<CookieAuthenticationOptions> context)
{
context.RedirectUri = $"/CustomReturnUrl";
return base.RedirectToReturnUrl(context);
}
}
Then register in startup:
services.AddScoped<XCookieAuthEvents>();
// optional: customize cookie expiration time
services.ConfigureApplicationCookie(ops =>
{
ops.EventsType = typeof(XCookieAuthEvents);
ops.ExpireTimeSpan = TimeSpan.FromMinutes(30);
ops.SlidingExpiration = true;
});