mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-29 19:12:27 +08:00
feat: 🎸 move totp services to encryption logic
This commit is contained in:
parent
687d506ca5
commit
5742d3068e
@ -111,7 +111,7 @@ interface OAuthStatus {
|
||||
}
|
||||
|
||||
interface TOTPStatus {
|
||||
enabled: boolean;
|
||||
set: boolean;
|
||||
message: boolean;
|
||||
}
|
||||
|
||||
@ -278,30 +278,21 @@ export default class MultiFactorAuthenticationOptions extends OptionsWidget {
|
||||
this.$oauthOptions.hide();
|
||||
}
|
||||
|
||||
server.get<OAuthStatus>("oauth/status").then((result) => {
|
||||
if (result.enabled) {
|
||||
if (result.name) this.$UserAccountName.text(result.name);
|
||||
if (result.email) this.$UserAccountEmail.text(result.email);
|
||||
// server.get<OAuthStatus>("oauth/status").then((result) => {
|
||||
// if (result.enabled) {
|
||||
// if (result.name) this.$UserAccountName.text(result.name);
|
||||
// if (result.email) this.$UserAccountEmail.text(result.email);
|
||||
|
||||
this.$envEnabledOAuth.hide();
|
||||
} else {
|
||||
this.$envEnabledOAuth.text(t("multi_factor_authentication.oauth_enable_description"));
|
||||
this.$envEnabledOAuth.show();
|
||||
}
|
||||
});
|
||||
// this.$envEnabledOAuth.hide();
|
||||
// } else {
|
||||
// this.$envEnabledOAuth.text(t("multi_factor_authentication.oauth_enable_description"));
|
||||
// this.$envEnabledOAuth.show();
|
||||
// }
|
||||
// });
|
||||
|
||||
server.get<TOTPStatus>("totp/status").then((result) => {
|
||||
if (result.enabled) {
|
||||
this.$generateTotpButton.prop("disabled", !result.message);
|
||||
this.$generateRecoveryCodeButton.prop("disabled", !result.message);
|
||||
|
||||
this.$envEnabledTOTP.hide();
|
||||
} else {
|
||||
this.$generateTotpButton.prop("disabled", true);
|
||||
this.$generateRecoveryCodeButton.prop("disabled", true);
|
||||
|
||||
this.$envEnabledTOTP.text(t("multi_factor_authentication.totp_enable_description"));
|
||||
this.$envEnabledTOTP.show();
|
||||
if (result.set) {
|
||||
this.$generateTotpButton.text(t("multi_factor_authentication.totp_secret_regenerate"));
|
||||
}
|
||||
});
|
||||
this.$protectedSessionTimeout.val(Number(options.protectedSessionTimeout));
|
||||
|
@ -1,20 +1,15 @@
|
||||
import { generateSecret } from 'time2fa';
|
||||
import config from '../../services/config.js';
|
||||
import totpService from '../../services/totp.js';
|
||||
|
||||
function generateTOTPSecret() {
|
||||
return { success: true, message: generateSecret() };
|
||||
}
|
||||
|
||||
function getTotpEnabled() {
|
||||
return config.MultiFactorAuthentication.totpEnabled;
|
||||
return totpService.createSecret();
|
||||
}
|
||||
|
||||
function getTOTPStatus() {
|
||||
return { success: true, message: getTotpEnabled(), enabled: getTotpEnabled() };
|
||||
return { success: true, message: totpService.isTotpEnabled(), set: totpService.checkForTotpSecret() };
|
||||
}
|
||||
|
||||
function getSecret() {
|
||||
return config.MultiFactorAuthentication.totpSecret;
|
||||
return totpService.getTotpSecret();
|
||||
}
|
||||
|
||||
export default {
|
||||
|
@ -8,7 +8,7 @@ const TOTP_OPTIONS: Record<string, OptionNames> = {
|
||||
SALT: "totpEncryptionSalt",
|
||||
ENCRYPTED_SECRET: "totpEncryptedSecret",
|
||||
VERIFICATION_HASH: "totpVerificationHash"
|
||||
} as const;
|
||||
};
|
||||
|
||||
function verifyTotpSecret(secret: string): boolean {
|
||||
const givenSecretHash = toBase64(myScryptService.getVerificationHash(secret));
|
||||
@ -21,20 +21,17 @@ function verifyTotpSecret(secret: string): boolean {
|
||||
return givenSecretHash === dbSecretHash;
|
||||
}
|
||||
|
||||
function setTotpSecret(secret: string): void {
|
||||
function setTotpSecret(secret: string) {
|
||||
if (!secret) {
|
||||
throw new Error("TOTP secret cannot be empty");
|
||||
}
|
||||
|
||||
// 生成新的加密盐值
|
||||
const encryptionSalt = randomSecureToken(32);
|
||||
optionService.setOption(TOTP_OPTIONS.SALT, encryptionSalt);
|
||||
|
||||
// 使用 scrypt 生成验证哈希
|
||||
const verificationHash = toBase64(myScryptService.getVerificationHash(secret));
|
||||
optionService.setOption(TOTP_OPTIONS.VERIFICATION_HASH, verificationHash);
|
||||
|
||||
// 使用数据加密密钥加密 TOTP secret
|
||||
const encryptedSecret = dataEncryptionService.encrypt(
|
||||
Buffer.from(encryptionSalt),
|
||||
secret
|
||||
@ -67,7 +64,7 @@ function getTotpSecret(): string | null {
|
||||
}
|
||||
}
|
||||
|
||||
function resetTotpSecret(): void {
|
||||
function resetTotpSecret() {
|
||||
optionService.setOption(TOTP_OPTIONS.SALT, "");
|
||||
optionService.setOption(TOTP_OPTIONS.ENCRYPTED_SECRET, "");
|
||||
optionService.setOption(TOTP_OPTIONS.VERIFICATION_HASH, "");
|
||||
|
@ -131,10 +131,10 @@ const defaultOptions: DefaultOption[] = [
|
||||
{ name: "customSearchEngineUrl", value: "https://duckduckgo.com/?q={keyword}", isSynced: true },
|
||||
{ name: "promotedAttributesOpenInRibbon", value: "true", isSynced: true },
|
||||
{ name: "editedNotesOpenInRibbon", value: "true", isSynced: true },
|
||||
{ name: 'totpEnabled', value: 'false', isSynced: true },
|
||||
{ name: "mfaEnabled", value: "false", isSynced: false },
|
||||
{ name: 'mfaMethod', value: 'totp', isSynced: false },
|
||||
{ name: 'encryptedRecoveryCodes', value: 'false', isSynced: true },
|
||||
{ name: 'userSubjectIdentifierSaved', value: 'false', isSynced: true },
|
||||
{ name: 'oAuthEnabled', value: 'false', isSynced: true },
|
||||
|
||||
// Appearance
|
||||
{ name: "splitEditorOrientation", value: "horizontal", isSynced: true },
|
||||
|
@ -1,40 +1,64 @@
|
||||
import { Totp } from 'time2fa';
|
||||
import config from './config.js';
|
||||
import MFAError from '../errors/mfa_error.js';
|
||||
import { Totp, generateSecret } from 'time2fa';
|
||||
import options from './options.js';
|
||||
import totpEncryptionService from './encryption/totp_encryption.js';
|
||||
|
||||
function isTotpEnabled(): boolean {
|
||||
return options.getOption('mfaEnabled') === "true" && options.getOption('mfaMethod') === "totp";
|
||||
}
|
||||
|
||||
function isTotpEnabled() {
|
||||
if (config.MultiFactorAuthentication.totpEnabled && config.MultiFactorAuthentication.totpSecret === "") {
|
||||
throw new MFAError("TOTP secret is not set!");
|
||||
function createSecret(): { success: boolean; message?: string } {
|
||||
try {
|
||||
const secret = generateSecret();
|
||||
|
||||
totpEncryptionService.setTotpSecret(secret);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: secret
|
||||
};
|
||||
} catch (e) {
|
||||
console.error('Failed to create TOTP secret:', e);
|
||||
return {
|
||||
success: false,
|
||||
message: e instanceof Error ? e.message : 'Unknown error occurred'
|
||||
};
|
||||
}
|
||||
return config.MultiFactorAuthentication.totpEnabled;
|
||||
}
|
||||
|
||||
function getTotpSecret() {
|
||||
return config.MultiFactorAuthentication.totpSecret;
|
||||
function getTotpSecret(): string | null {
|
||||
return totpEncryptionService.getTotpSecret();
|
||||
}
|
||||
|
||||
function checkForTotSecret() {
|
||||
return config.MultiFactorAuthentication.totpSecret === "" ? false : true;
|
||||
function checkForTotpSecret(): boolean {
|
||||
return totpEncryptionService.isTotpSecretSet();
|
||||
}
|
||||
|
||||
function validateTOTP(submittedPasscode: string) {
|
||||
if (config.MultiFactorAuthentication.totpSecret === "") return false;
|
||||
function validateTOTP(submittedPasscode: string): boolean {
|
||||
const secret = getTotpSecret();
|
||||
if (!secret) return false;
|
||||
|
||||
try {
|
||||
const valid = Totp.validate({
|
||||
return Totp.validate({
|
||||
passcode: submittedPasscode,
|
||||
secret: config.MultiFactorAuthentication.totpSecret.trim()
|
||||
secret: secret.trim()
|
||||
});
|
||||
return valid;
|
||||
} catch (e) {
|
||||
console.error('Failed to validate TOTP:', e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function resetTotp(): void {
|
||||
totpEncryptionService.resetTotpSecret();
|
||||
options.setOption('mfaEnabled', 'false');
|
||||
options.setOption('mfaMethod', '');
|
||||
}
|
||||
|
||||
export default {
|
||||
isTotpEnabled,
|
||||
createSecret,
|
||||
getTotpSecret,
|
||||
checkForTotSecret,
|
||||
validateTOTP
|
||||
};
|
||||
checkForTotpSecret,
|
||||
validateTOTP,
|
||||
resetTotp
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user