-
-
-
-
${t("multi_factor_authentication.oauth_user_account")} ${t("multi_factor_authentication.oauth_user_not_logged_in")}
@@ -157,10 +133,8 @@ interface RecoveryKeysResponse {
export default class MultiFactorAuthenticationOptions extends OptionsWidget {
private $generateTotpButton!: JQuery;
- private $totpEnabled!: JQuery;
private $totpSecret!: JQuery;
private $generateRecoveryCodeButton!: JQuery;
- private $oAuthEnabledCheckbox!: JQuery;
private $UserAccountName!: JQuery;
private $UserAccountEmail!: JQuery;
private $envEnabledTOTP!: JQuery;
@@ -169,7 +143,7 @@ export default class MultiFactorAuthenticationOptions extends OptionsWidget {
private $protectedSessionTimeout!: JQuery;
private $mfaEnabledCheckbox!: JQuery;
private $mfaOptions!: JQuery;
- private $authMethodRadios!: JQuery;
+ private $mfaMethodRadios!: JQuery;
private $totpOptions!: JQuery;
private $oauthOptions!: JQuery;
@@ -180,15 +154,13 @@ export default class MultiFactorAuthenticationOptions extends OptionsWidget {
if (!utils.isElectron()) {
this.$mfaEnabledCheckbox = this.$widget.find(".mfa-enabled-checkbox");
this.$mfaOptions = this.$widget.find(".mfa-options");
- this.$authMethodRadios = this.$widget.find(".auth-method-radio");
+ this.$mfaMethodRadios = this.$widget.find(".mfa-method-radio");
this.$totpOptions = this.$widget.find(".totp-options");
this.$oauthOptions = this.$widget.find(".oauth-options");
this.$generateTotpButton = this.$widget.find(".generate-totp");
- this.$totpEnabled = this.$widget.find(".totp-enabled");
this.$totpSecret = this.$widget.find(".totp-secret");
this.$generateRecoveryCodeButton = this.$widget.find(".generate-recovery-code");
- this.$oAuthEnabledCheckbox = this.$widget.find(".oauth-enabled-checkbox");
this.$UserAccountName = this.$widget.find(".user-account-name");
this.$UserAccountEmail = this.$widget.find(".user-account-email");
this.$envEnabledTOTP = this.$widget.find(".env-totp-enabled");
@@ -215,17 +187,24 @@ export default class MultiFactorAuthenticationOptions extends OptionsWidget {
this.displayRecoveryKeys();
this.$mfaEnabledCheckbox.on("change", () => {
- this.$mfaOptions.toggle(this.$mfaEnabledCheckbox.is(":checked"));
- if (!this.$mfaEnabledCheckbox.is(":checked")) {
+ const isChecked = this.$mfaEnabledCheckbox.is(":checked");
+ this.$mfaOptions.toggle(isChecked);
+ if (!isChecked) {
this.$totpOptions.hide();
this.$oauthOptions.hide();
+ } else {
+ this.$mfaMethodRadios.filter('[value="totp"]').prop("checked", true);
+ this.$totpOptions.show();
+ this.$oauthOptions.hide();
}
+ this.updateCheckboxOption("mfaEnabled", this.$mfaEnabledCheckbox);
});
- this.$authMethodRadios.on("change", () => {
- const selectedMethod = this.$authMethodRadios.filter(":checked").val();
+ this.$mfaMethodRadios.on("change", () => {
+ const selectedMethod = this.$mfaMethodRadios.filter(":checked").val();
this.$totpOptions.toggle(selectedMethod === "totp");
this.$oauthOptions.toggle(selectedMethod === "oauth");
+ this.updateOption("mfaMethod", selectedMethod);
});
}
}
@@ -295,9 +274,21 @@ export default class MultiFactorAuthenticationOptions extends OptionsWidget {
optionsLoaded(options: OptionMap) {
if (!utils.isElectron()) {
+ this.$mfaEnabledCheckbox.prop("checked", options.mfaEnabled === "true");
+
+ this.$mfaOptions.toggle(options.mfaEnabled === "true");
+ if (options.mfaEnabled === "true") {
+ const savedMethod = options.mfaMethod || "totp";
+ this.$mfaMethodRadios.filter(`[value="${savedMethod}"]`).prop("checked", true);
+ this.$totpOptions.toggle(savedMethod === "totp");
+ this.$oauthOptions.toggle(savedMethod === "oauth");
+ } else {
+ this.$totpOptions.hide();
+ this.$oauthOptions.hide();
+ }
+
server.get("oauth/status").then((result) => {
if (result.enabled) {
- this.$oAuthEnabledCheckbox.prop("checked", result.enabled);
if (result.name) this.$UserAccountName.text(result.name);
if (result.email) this.$UserAccountEmail.text(result.email);
@@ -310,14 +301,11 @@ export default class MultiFactorAuthenticationOptions extends OptionsWidget {
server.get("totp/status").then((result) => {
if (result.enabled) {
- this.$totpEnabled.prop("checked", result.message);
this.$generateTotpButton.prop("disabled", !result.message);
this.$generateRecoveryCodeButton.prop("disabled", !result.message);
this.$envEnabledTOTP.hide();
} else {
- this.$totpEnabled.prop("checked", false);
- this.$totpEnabled.prop("disabled", true);
this.$generateTotpButton.prop("disabled", true);
this.$generateRecoveryCodeButton.prop("disabled", true);
diff --git a/src/routes/api/options.ts b/src/routes/api/options.ts
index 1716d5126..140e2448e 100644
--- a/src/routes/api/options.ts
+++ b/src/routes/api/options.ts
@@ -80,7 +80,9 @@ const ALLOWED_OPTIONS = new Set([
"allowedHtmlTags",
"redirectBareDomain",
"showLoginInShareTheme",
- "splitEditorOrientation"
+ "splitEditorOrientation",
+ "mfaEnabled",
+ "mfaMethod"
]);
function getOptions() {
diff --git a/src/services/options_interface.ts b/src/services/options_interface.ts
index 20a9a6c31..258ee9195 100644
--- a/src/services/options_interface.ts
+++ b/src/services/options_interface.ts
@@ -49,10 +49,10 @@ export interface OptionDefinitions extends KeyboardShortcutsOptions