The above is our standard configuration for all customers. FortiGate/FortiClient IPsec VPNs, RADIUS server using PAP which connects to the Duo RADIUS proxy server, which then authenticates against MS NPS and upon succeeding contacts the Duo API for 2FA. This is working well for us with no issues.
Previously we worked with Duo support and determined a caveat. Users are able to specify the Duo 2FA method using a delimiter in the password string (for example, "password,push" would perform send a push prompt to the user's phone, "password,phone" would call the user with a voice prompt, etc.). This was a much-desired accommodation for some customers, however the drawback was that PAP had to be used so that the Duo RADIUS proxy server could parse out the password string and read the specified 2FA method after the delimiter. Using PAP meant we would no longer be able to let users change their password over VPN once it had expired which we do by using MSCHAPv2. So the end result is that we would have the customer choose whether they wanted users to be able to specify their 2FA method or if they wanted users to be able to change their password over VPN after they'd expired.
However, we are now able to change our password over VPN after it had expired while using PAP on the FGT and while specifying the Duo 2FA method in the password string. I have verified the request hits our MS NPS servers as MSCHAPv2 when the password needs to be changed, and hits it as PAP when it doesn't need to be changed. I see two possibilities:
1. Configuring password-renewal enable on a RADIUS server on the FGT changes the behavior to use MSCHAPv2 and ignore the configuration in place that specifies PAP. The Duo RADIUS proxy server has gotten an update and now decrypts the MSCHAPv2 password string on the fly (since this encryption is extremely broken at this point and it little more than obscurity), parses the specified 2FA method after the delimiter, strips it, and finally sends the MSCHAPv2 request on to the MS NPS server.
2. The FGT continues to use PAP as configured, so the Duo RADIUS proxy server parses the 2FA method out of the password string without issue. The Duo RADIUS proxy server then uses MSCHAPv2 to auth against MS NPS, either by default if it can detect it supports it, or as a reaction to a response from the MS NPS server indicating expired credentials.
I would expect option #2 is more likely since we see the request hit NPS as PAP when a password change is not required. I will also note that it appears we cannot change the password AND specify the 2FA method in a single auth attempt (though I have not tested this thoroughly). I have reached out to Duo and will post back with any response I get from them (nothing relevant in their release notes). In any case, this is certainly a huge benefit for us and our customers, just wanted to share for anyone who has faced this scenario/challenge. Update your Duo proxy, use PAP and the password-renewal config on the FGT, ensure both PAP and MSCHAPv2 w/pass change are allowed in NPS, and you should be in good shape!