Custom logic for a dynamic login page

This solution is for having multiple or dynamic login paths for the same authentication provider. Out of the box ASP.NET Core, you define a login path when configuring the authentication provider in startup.cs. But you can only define one path for a single authentication provider.

An example would be If you want to keep the default Optimizely login url for admins but also have a separate custom style page login for users.

(In Optimizely, the login path is '<site>/util/login')

ASP.NET Core offers the IAuthorizationMiddlewareResultHandler which allows you to customize the handling of authentication or authorization response.

In our example we want to customize the authentication response when the user has been challenged. In other words, they have requested to access a resource they are currently not authorized against and ASP.NET Core is redirecting them to the default behaviour. In our case is the login path.

We want to enhance this by working out which resource they were trying to access and send them to the relevant login path.

Code Example


public class LoginRedirectAuthorizationMiddlewareResultHandler : IAuthorizationMiddlewareResultHandler
{
private readonly AuthorizationMiddlewareResultHandler defaultHandler = new();
private readonly IUrlResolver urlResolver;
private readonly IContentLoader _contentLoader; public LoginRedirectAuthorizationMiddlewareResultHandler(IUrlResolver urlResolver, IContentLoader contentLoader)
{
this.urlResolver = urlResolver;
_contentLoader = contentLoader;
} public async Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult) { var isEpiserverAdminUrl = context.Request.Path.StartsWithSegments(new PathString("/episerver")); if (authorizeResult.Challenged && !isEpiserverAdminUrl)
{
var loginPage = GetLoginPage();
var url = urlResolver.GetUrl(loginPage?.ContentLink); context.Response.Redirect(url);
return;
}

await defaultHandler.HandleAsync(next, context, policy, authorizeResult); } </pre class="language-csharp">