Credentials Flow / Two Factor Authentication

Any insights on how to implement a Credentials Flow with 2FA? There seems to be very little out there on how to implement this type of solution.

We would like to authenticate them, check to see if MFA has been set up, if so, verify the MFA otherwise set up the MFA. Regardless we want to prevent them from using the site until MFA has been verified.

Any suggestions/ideas/direction you can give would be helpful.

2FA is basically a UI flow that occurs outside of (i.e. before) Authentication where basically you have a Service that firsts validates whether they have a valid password which you can validate against your Auth Provider in your Services with:

if (AuthRepository.TryAuthenticate(username, password, out var userAuth) {
 //..
}

Which could redirect to a UI that accepts their 2FA code. The ASP.NET Core docs shows an example of using Twilio to implement 2FA via SMS.

After you validate their 2FA code you can either Authenticate them with an In Process Authentication Request as seen below, otherwise you could save their password in their base.SessionBag and use their real password to authenticate them.

In Process Authenticated Requests

You can enable the CredentialsAuthProvider to allow In Process requests to Authenticate without a Password with:

new CredentialsAuthProvider {
    SkipPasswordVerificationForInProcessRequests = true,
}

When enabled this lets In Process Service Requests to login as a specified user without needing to provide their password.

For example this could be used to create an Intranet Restricted Admin-Only Service that lets you login as another user so you can debug their account without knowing their password with:

[RequiredRole("Admin")]
[Restrict(InternalOnly=true)]
public class ImpersonateUser 
{
    public string UserName { get; set; }
}

public class MyAdminServices : Service
{
    public object Any(ImpersonateUser request)
    {
        using (var service = base.ResolveService<AuthenticateService>()) //In Process
        {
            return service.Post(new Authenticate {
                provider = AuthenticateService.CredentialsProvider,
                UserName = request.UserName,
                UseTokenCookie = true, // if using JWT
            });
        }
    }
}

If I validate the users 2FA code and then Authenticate the user with an In Process Authenticated Request, how can I prevent users from authenticating via the built-in CredentialsAuthProvider (POST to /auth/credentials) and thereby bypassing the 2FA requirement? Is there a way to enable access to CredentialsAuthProvider for InProcess requests only?

You can add custom validation logic to Authenticate requests with a CustomValidationFilter or for more flexibility you can take over the Authentication with a Custom AuthProvider that performs the additional validation.

If needed, you can check if a request is in-process with the IRequest.IsInProcessRequest() extension method, should you want to bypass validation for in-process requests.

1 Like