sandstorm / NeosTwoFactorAuthentication

Extend the Neos Backend Login with 2FA
MIT License
12 stars 8 forks source link
2fa neos neos-cms

Neos Backend 2FA

Extend the Neos backend login to support second factors. At the moment we only support TOTP tokens.

Support for WebAuthn is planed!

What this package does

https://user-images.githubusercontent.com/12086990/153027757-ac715746-0575-4555-bce1-c44603747945.mov

This package allows all users to register their personal TOTP token (Authenticator App). As an Administrator you are able to delete those token for the users again, in case they locked them self out.

Screenshot 2022-02-08 at 17 11 01

Settings

Enforce 2FA

To enforce the setup and usage of 2FA you can add the following to your Settings.yaml.

Sandstorm:
    NeosTwoFactorAuthentication:
        # enforce 2FA for all users
        enforceTwoFactorAuthentication: true

With this setting, no user can login into the CMS without setting up a second factor first.

In addition, you can enforce 2FA for specific authentication providers and/or roles by adding following to your Settings.yaml

Sandstorm:
    NeosTwoFactorAuthentication:
      # enforce 2FA for specific authentication providers
      enforce2FAForAuthenticationProviders : ['Neos.Neos:Backend']
      # enforce 2FA for specific roles
      enforce2FAForRoles: ['Neos.Neos:Administrator']  

Issuer Naming

To override the default sitename as issuer label, you can define one via the configuration settings:

Sandstorm:
    NeosTwoFactorAuthentication:
        # (optional) if set this will be used as a naming convention for the TOTP. If empty the Site name will be used
        issuerName: ''

Tested 2FA apps

Thx to @Sebobo @Benjamin-K for creating a list of supported and testet apps!

iOS:

Android:

How we did it

When updating Neos, those part will likely crash:

Why not ...?

Enhance the UsernamePassword authentication token

This actually has been the approach up until version 1.0.5.

One issue with this is the fact, that we want the user to be logged in with that token via the PersistedUsernamePasswordProvider, but at the same time to not be logged in with that token as long as 2FA is not authenticated as well. We found it hard to find a secure way to model the 2FA setup solution when 2FA is enforced, but the user does not have a second factor enabled, yet.

The middleware approach makes a clear distinction between "Logging in" and "Second Factor Authentication", while still being session based and unable to bypass.

Set the authenticationStrategy to allTokens

The AuthenticationProviderManager requires to authorize all tokens at the same time otherwise, it will throw an Exception (see AuthenticationProviderManager Line 181

if ($this->authenticationStrategy === Context::AUTHENTICATE_ALL_TOKENS) {
    throw new AuthenticationRequiredException('Could not authenticate all tokens, but authenticationStrategy was set to "all".', 1222203912);
}

)

This leads to an error where the AuthenticationProviderManager throws exceptions before the user is able to enter any credentials. The SecurityEntryPointMiddleware catches those exceptions and redirects to the Neos Backend Login, which causes the same exception again. We get caught in an endless redirect.

The Neos Flow Security Documentation suggests how to implement a multi-factor-authentication, but this method seems like it was never tested. At the moment of writing it seems like the authenticationStrategy: allTokens flag is broken and not usable.