I'm writing a Razor Pages application running on .Net 5.0. This application needs to be able to support members of staff (who sign in with Windows authentication) and applicants (who don't have a Windows account, so need to register/login with a custom authentication process). I can either get Windows auth or custom auth to work, but the two don't want to play ball together!!
I believe I need to write a custom implementation of IAuthenticationService but this is where it's tripping me up. I can't work out what I need to do in ChallengeAsync in order to let the challenge pass!
Here's the AuthService implementation at the moment (yes, it's not the nicest, but my focus at this point is on getting it working!!):
public class AuthService : IAuthenticationService
{
async Task<AuthenticateResult> IAuthenticationService.AuthenticateAsync(HttpContext context, string scheme)
{
if (HasAnonymousAttribute(context))
{
return AuthenticateResult.NoResult();
}
var user = getUser(context);
if (user != null)
{
var ticket = new AuthenticationTicket(user, "magic");
return AuthenticateResult.Success(ticket);
}
await context.ChallengeAsync("Windows");
if (context.User.Identity.IsAuthenticated)
{
var ticket = new AuthenticationTicket(context.User, "Windows");
return AuthenticateResult.Success(ticket);
}
return AuthenticateResult.Fail("Please log in");
}
Task IAuthenticationService.ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties)
{
var user = context.Session.Get("User");
if (user == null)
{
//do something to block the user from access
}
return Task.FromResult(0);
}
Task IAuthenticationService.ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties)
{
throw new NotImplementedException();
}
Task IAuthenticationService.SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties)
{
if(scheme.ToLower() == "magic")
{
context.Session.Set("User", Encoding.ASCII.GetBytes(principal.Identity.Name));
}
return Task.FromResult(0);
}
Task IAuthenticationService.SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties)
{
throw new NotImplementedException();
}
private ClaimsPrincipal getUser(HttpContext context)
{
if (context.User.Identity.IsAuthenticated)
{
return (ClaimsPrincipal)context.User.Identity;
}
return null;
}
private bool HasAnonymousAttribute(HttpContext context)
{
var endpoint = context.GetEndpoint();
var retVal = (endpoint?.Metadata?.GetMetadata<IAllowAnonymous>() != null);
return retVal;
}
}