Class AbstractMfaProcess
- java.lang.Object
-
- eu.webtoolkit.jwt.WObject
-
- eu.webtoolkit.jwt.auth.mfa.AbstractMfaProcess
-
- Direct Known Subclasses:
TotpProcess
public abstract class AbstractMfaProcess extends WObject
The interface for a second factor authentication process.This class defines the interface to be used when implementing a second factor in the authentication flow. Currently, it is strongly advised (by among others OWASP) that a second factor is added to any authentication module.
When a developer wishes to enable MFA they will need to set the
AuthService#setMfaProvider(), and optionallyAuthService#setMfaRequired(). This will enable JWt to display the MFA step to users logging into the system. This will be shown after a user:- logs in (with username/password)
- is authenticated with a login cookie
The MFA step can be either the setup view, which holds the initial state for the MFA method. For JWt's default, this means a QR code with the TOTP secret encoded. This then adds an
Identityto the user, by which they can be authenticated against a certain provider. The secret key is also displayed, so that it can be copied into a password manager or authenticator app.For this to work, a developer needs to implement
createSetupView(). The method creates the widget that displays the view. This view tells the user how to set up the MFA step. The defaultTotpProcesswill bind the content to a template. But developers are free to use their own way (like showing a pop-up) This will require the developer to override theAuthWidget.createMfaView().After this setup, the process can be repeated but a simpler view is often desired here, one that no longer hold any configuration state, but simply asks for a token of authentication. This is where
createInputView()comes into play. This functions the exact same way as the above setup view counterpart, but shows less information. Again, for JWt's default implementation, using TOTP, this means a 6 (depending on configuration, see:AuthService#setMfaCodeLength()) digit code, that is generated from their secret key will be asked of the user. The initial (QR) code that serves as the way to generate the TOTP keys, will no longer be displayed.A successful match of the second factor will then result in an actual login (
Login#login()) (see the note).To use your own widget in the normal authentication flow, one also needs to override
AuthWidget.createMfaProcess(), so that it will create the correct widget. By default this will create theTotpProcess.Note: The
Login.changed()signal will be fired both when the user logs in with username/password, and when the MFA step is completed successfully. If your application listens to this signal to determine some state or logic, you should check whether the login has taken place fully (based on the LoginState (Login.getState())). For convenience it's a good idea to make your custom widget fire a signal when it tries to authenticate- See Also:
AuthenticationResult
-
-
Nested Class Summary
-
Nested classes/interfaces inherited from class eu.webtoolkit.jwt.WObject
WObject.FormData
-
-
Field Summary
Fields Modifier and Type Field Description protected intthrottlingDelay_
-
Constructor Summary
Constructors Constructor Description AbstractMfaProcess(AuthService authService, AbstractUserDatabase users, Login login)Constructor.
-
Method Summary
All Methods Instance Methods Abstract Methods Concrete Methods Modifier and Type Method Description protected voidconfigureThrottling(WInteractWidget button)Configures client-side throttling on the process.abstract WWidgetcreateInputView()Creates the view that displays the MFA input step.abstract WWidgetcreateSetupView()Creates the view that displays the MFA configuration step.protected booleancreateUserIdentity(java.lang.CharSequence identityValue)protected AuthServicegetBaseAuth()protected LogingetLogin()protected AuthThrottlegetMfaThrottle()protected UsergetProcessMfaToken()Processes an MFA authentication token.java.lang.StringgetProvider()Returns the name of the provider for the process.protected WStringgetUserIdentity()Retrieves the currentUser's identity for the provider.protected AbstractUserDatabasegetUsers()voidprocessEnvironment()Processes the (initial) environment.voidsetMfaThrottle(AuthThrottle authThrottle)Sets the instance that manages throttling.protected voidsetRememberMeCookie(User user)Creates an MFA authentication token.protected voidupdateThrottling(WInteractWidget button)Updates client-side login throttling on the process.-
Methods inherited from class eu.webtoolkit.jwt.WObject
getId, getObjectName, remove, setFormData, setObjectName, tr
-
-
-
-
Constructor Detail
-
AbstractMfaProcess
public AbstractMfaProcess(AuthService authService, AbstractUserDatabase users, Login login)
Constructor.
-
-
Method Detail
-
getProvider
public java.lang.String getProvider()
Returns the name of the provider for the process.
-
processEnvironment
public void processEnvironment()
Processes the (initial) environment.This can be called to tell the widget to look through the environment for the relevant cookies. It will handle the side-effect of finding such a cookie, and it still being valid. The user will be logged in, in a weak state (
LoginState.Weak), and the authenticated() signal will be fired, with anAuthenticationStatus.Success.
-
createSetupView
public abstract WWidget createSetupView()
Creates the view that displays the MFA configuration step.This is the view that is shown to a user if they do not have MFA enabled yet. This will often show more information to them, telling them how the feature is to be used and activated.
The state of whether a user has MFA enabled or not can be decided in two ways:
- the feature is enabled (
AuthService.getMfaProvider()isn't empty) and they have an identity for the provider. By default JWt's TOTP implementation will take theIdentity.MultiFactorname as the provider. - the feature is enabled AND required (
AuthService.isMfaRequired()is set totrue)
- the feature is enabled (
-
createInputView
public abstract WWidget createInputView()
Creates the view that displays the MFA input step.The user already has an identity attached to their record. This step now needs valid input from them to continue.
- See Also:
createSetupView()
-
setMfaThrottle
public void setMfaThrottle(AuthThrottle authThrottle)
Sets the instance that manages throttling.Throtteling is an additional safety measure. It ensures that the MFA process cannot be brute-forced.
Setting the throttler, will allow for it to be configured (
configureThrottling()), and updated (updateThrottling()) if applicable.
-
getUserIdentity
protected WString getUserIdentity()
Retrieves the currentUser's identity for the provider.This is simply a method that retrieves the current
User's identity, given the provider the process specified (seegetProvider()). This can be accessed by callingUser#getIdentity()as well.The method will return the identity, if it exists, or an empty string if it does not. It will also log (to "warn") in the latter case.
-
createUserIdentity
protected boolean createUserIdentity(java.lang.CharSequence identityValue)
Adds anIdentityto the currentUserwith the given value.The identity will be created with the specified
getProvider()on the process. And the actual identity will beidentityValue.This is again a method that offers very basic functionality, calling:
User#getIdentity()andUser#addIdentity(), with some logging added to it.Note: This will store the value in plaintext in the database. Should your chosen method of MFA want this to be stored in a more secure manner, the developer will have to do this manually (or the database itself should be encrypted).
- See Also:
getUserIdentity()
-
getProcessMfaToken
protected User getProcessMfaToken()
Processes an MFA authentication token.If a token is present in the browser, going by the name found in
AuthService.getMfaTokenCookieName(), and that is still valid (seeAuthService.getMfaTokenValidity()), theUsercan be retrieved from that token. This identifies the user uniquely, ensuring their MFA verification step can be skipped for a certain period.
-
setRememberMeCookie
protected void setRememberMeCookie(User user)
Creates an MFA authentication token.A token (with the correct prefix for MFA) is created and persisted in the database. A cookie is created in the
user'sbrowser. This token can later be used bygetProcessMfaToken()to identify theUser, allowing them to skip the MFA step.
-
configureThrottling
protected void configureThrottling(WInteractWidget button)
Configures client-side throttling on the process.If attempt throttling is enabled, then this may also be indicated client-side using JavaScript by disabling the login button and showing a count-down indicator. This method initializes this JavaScript utility function for a login button.
If throttling is enabled, it may be necessary for a custom implementation to manage this state itself. This is to allow developers the freedom to define their own MFA processes.
Look at
TotpProcess#verifyCode()for an example.- See Also:
updateThrottling(WInteractWidget button)
-
updateThrottling
protected void updateThrottling(WInteractWidget button)
Updates client-side login throttling on the process.This should be called after a MFA authentication event takes place, if you want to reflect throttling using a client-side count-down indicator on the button.
You need to call
configureThrottling()before you can do this.If throttling is enabled, it may be necessary for a custom implementation to manage this state itself. This is to allow developers the freedom to define their own MFA processes.
Look at
TotpProcess#verifyCode()for an example.
-
getBaseAuth
protected AuthService getBaseAuth()
-
getUsers
protected AbstractUserDatabase getUsers()
-
getLogin
protected Login getLogin()
-
getMfaThrottle
protected AuthThrottle getMfaThrottle()
-
-