It looks like standard two factor authentication is not available for community users. Does anybody know a work-around for this?
Two Factor Authentication is supported for Community Users as pointed out by Rob Cowell.
For standard user license type, you my be accustomed to enabling 2FA via the System Permission
Two-Factor Authentication for API Logins and
Two-Factor Authentication for User Interface Logins. However, you might not see these options for community profiles.
Per Set Two-Factor Authentication Login Requirements and Custom Policies for Single Sign-On, Social Sign-On, and Communities, you need to modify the community profile's Session Settings and set
Session security level required at login to be High Assurance.
When user attempts to login to community with their
password then they will automatically be prompted to provide 2FA. Here's screen shot of a community user being prompted to setup Salesforce Authenticator app for the first time:
At the time of writing (Mar 2016), I believe Two-factor is available for Community Users, based on what I'm seeing at https://help.salesforce.com/HTViewHelpDoc?id=two_factor_auth_for_sso_and_saml.htm&language=en_US
However, your process allows for a far greater degree of customisation, so upvoted accordingly.
You are correct, Two-Factor Authentication is not available for users with a Partner Community or Customer Community license.
However, there is a no-code workaround: you can implement Two-Factor Authentication for Community Users by creating a custom Login Flow. Login Flows override the default Salesforce login screen, so that your users are taken through your Flow before logging in. This allows you to implement whatever logic you need to verify a user before allowing them to login. Login Flows can be assigned to Partner or Customer Community profiles.
Here is a tutorial that outlines how to do this for an email-based Two Factor Authentication scenario:
In a nutshell, the process is this: Your Login Flow creates a record in a custom object which randomly generates Security Tokens (e.g. 6-character numbers) associated with a unique user identifier, such as the email address or username. The Flow then sends the user an email with the generated Security Token, and presents the user with a screen where they are asked to enter the Security Token. If the token matches what's in the record, then the user is allowed to login, otherwise the user is denied.
The approach described in this blog post could be adapted to have the security token be sent via SMS rather than email by making a call to an Apex Invocable Action that calls the Twilio REST API - start on Slide 11 of this SlideShare for an overview (unfortunately I don't think there's any code here, but Twilio's REST API for sending SMS messages is pretty straightforward and could easily be adapted into an Invocable Action)