@wwalker – If interested, we just finished doing exactly, I think, what you want. What we have is:
- Cisco ASA 5516 redundant pair, ASA 9.12.2
- Cisco ASDM 7.12.2
- Cisco AnyConnect 4.7
AnyConnect, rather than old-school IPsec RA, is needed because it seamlessly handles the 2nd-level prompting for MFA credentials. (We upgraded to those specific latest versions because the translation tables necessary for changing the UI prompts had bugs.)
Our PI server is v3.0.2, and we link to AD users using the LDAP resolver. We use freeRADIUS 2.2.8 with the Perl plugin. Understand that the freeRADIUS plugin is intended solely to translate PI requests to RADIUS and then give back RADIUS-compliant answers. You are not populating RADIUS with any data or forwarding to Windows NPS, etc.
We use the PI server configured with otppin=tokenpin and login_mode=privacyIDEA. It’s a bit misleading that the login_mode is a webui policy, because that policy actually applies to any login including an API request via the RADIUS plugin.
The magic happens when you configure your AnyConnect profile to use a secondary authentication model. The first username/password applies to your LDAP query that (presumably) is being sent to NPS for domain credentials. The secondary RADIUS auth is then used to query freeRADIUS for the associated MFA token. You can have a secondary username/password prompt, or, since you are resolving to the same LDAP that PI is using, prompt only for the password using the common samAccountName:
tunnel-group AnyConnectVPN general-attributes
secondary-authentication-server-group PrivacyIDEA use-primary-username
The setup works great for single-step TOTP/HOTP, which was to be expected. But to really blow your mind, it also works with Email and U2F because of the RADIUS challenge-response support and the ability of the AnyConnect client to understand that handshake and provide the necessary 2nd-level prompts. (Make sure users configure a PIN on their C-R tokens, because that is what is needed to trigger the appropriate challenge.)