Two Factor Authentication#
Structr supports the TOTP (Time-Based One-Time Password) flavor of two-factor authentication and supports multiple configuration options to enable two-factor-authentication. They can be configured via structr.conf or the configuration servlet (http://<your-structr>/structr/config
).
Note: Because the TOTP algorithm is used, it is important that the clocks of both factors (server and mobile device) are synced to a NTP server so they are as close as possible.
Configuration Options
security.twofactorauthentication.level
0
= off
Two-Factor Authentication is turned off completely1
= optional (Default)
Two-Factor Authentication can be turned on on a per-user basis.2
= forced
Every user is forced to use Two-Factor Authentication
security.twofactorauthentication.issuer
The issuer parameter is a string value indicating the provider or service this account is associated with, URL-encoded according to RFC 3986. If the issuer parameter is absent, issuer information may be taken from the issuer prefix of the label. If both issuer parameter and issuer label prefix are present, they should be equal.
Valid values corresponding to the label prefix examples above would be: issuer=Example, issuer=Provider1, and issuer=Big%20Corporation.
Older Google Authenticator implementations ignore the issuer parameter and rely upon the issuer label prefix to disambiguate accounts. Newer implementations will use the issuer parameter for internal disambiguation, it will not be displayed to the user. We recommend using both issuer label prefix and issuer parameter together to safely support both old and new Google Authenticator versions.
security.twofactorauthentication.algorithm
The algorithm may have the values:
SHA1
(Default)SHA256
SHA512
Warning: Changing this setting after users are already confirmed will effectively lock them out. Set <User>.twoFactorConfirmed
to false
to show them a new QR code.
security.twofactorauthentication.digits
OPTIONAL: The digits parameter may have the values 6
or 8
, and determines how long of a one-time passcode to display to the user. The default is 6.
Warning: Changing this setting after users are already confirmed may lock them out. Set <User>.twoFactorConfirmed
to false
to show them a new QR code.
security.twofactorauthentication.period
OPTIONAL only if type is totp: The period parameter defines a period that a TOTP code will be valid for, in seconds. The default value is 30
.
Warning: Changing this setting after users are already confirmed may lock them out. Set <User>.twoFactorConfirmed
to false
to show them a new QR code.
security.twofactorauthentication.logintimeout
Defines how long the two-factor login time window in seconds is. After entering the username and password the user has this amount of time to enter a two factor token before he has to re-authenticate via password. Default is 30
.
security.twofactorauthentication.loginpage
The application page where the user enters the current two factor token. Until the user has verified his two factor token (by logging in once), the user is shown a QR code after every login attempt. Default is /twofactor
Note: To allow maximum flexibility, this page is part of the web-application and not part of Structr.
security.twofactorauthentication.whitelistedIPs
A comma-separated (,) list of IPs for which two factor authentication is disabled.
User configuration
There are three main properties you can change to control the two factor authentication behaviour for a specific user node.
User.twoFactorConfirmed
This is automatically set to true after a user authenticates via two-factor authentication. If this is set to false the user will always be shown the QR code for him to scan.User.isTwoFactorUser
Controls if the user wants to authenticate via two factor authentication. This only works if the settingTwoFactor.level
is set to1
. If the setting is set to2
, the flag will automatically be set totrue
after a user logs in.User.twoFactorSecret
This is the secret which is used to generate tokens. It is automatically generated for every user.
Example implementation
- Create the basic login page as per usual
- If this is done using
Edit Mode Binding
no changes are necessary - If the login is done with custom JavaScript we need to react to status code 202 like so:
202: function(resp, txt, xhr) { var redirectUrl = xhr.getResponseHeader('twoFactorLoginPage') + '?token=' + xhr.getResponseHeader('token'); var qrdata = xhr.getResponseHeader('qrdata'); if (qrdata) { redirectUrl += '&qrdata=' + qrdata; } window.location.href = redirectUrl; }
- If this is done using
- Create the
TwoFactor.loginpage
with the following HTML nodes with the givenEdit Mode Binding
configuration. (since the qrdata was transferred as URL-safe base64 and img tags only support regular base64 data URIs we need to convert it).
Note: Since this form usesEdit Mode Binding
it is highly advised to create real HTML nodes in structr for the below HTML.<div data-structr-meta-hide-conditions="empty(request.qrdata)"> <img id="qrimage" src="data:image/png;base64, ${str_replace(str_replace(request.qrdata, '_', '/'), '-', '+')}" style="margin-left: calc(50% - 100px);"> <div>Scan this QR code to use two factor authentication</div> </div> <form action="#" id="loginForm"> <input name="twoFactorToken" type="hidden" value="${request.token}" data-structr-name="twoFactorToken"> <div class="form-group"> <label class="control-label" for="password">Two Factor Code</label> <input class="form-control" name="twoFactorCode" required="" type="text" data-structr-name="twoFactorCode"> </div> <button data-structr-action="login" data-structr-attributes="twoFactorToken, twoFactorCode" data-structr-return="/dashboard">Login</button> </form>
- After a successful password-login, the user is redirected to the two-factor authentication page where he has to enter a one-time-password (OTP)
- If the OTP was correct, the user is allowed to continue (and will not be shown the QR code the next time he logs in)