chore: Add serverPassword param to endpoints (#2919) [skip e2e]

* chore: send server password param to delete account endpoint

* chore: send server password param to disable mfa endpoint

* chore: modify tests

* chore: force challenge prompt for mfa disable

* chore: fix eslint errors

* chore: add server passsword to get recovery codes

* chore: fix tests

* chore: pass server password as header
This commit is contained in:
Antonella Sgarlatta
2025-08-26 09:04:03 -03:00
committed by GitHub
parent cf4d2196de
commit 54af28aa04
29 changed files with 298 additions and 62 deletions

View File

@@ -2,7 +2,7 @@ import { AnyKeyParamsContent } from '@standardnotes/common'
import { SessionBody } from '@standardnotes/responses'
export interface AuthClientInterface {
generateRecoveryCodes(): Promise<string | false>
generateRecoveryCodes(dto: { serverPassword: string }): Promise<string | false>
recoveryKeyParams(dto: {
username: string
codeChallenge: string

View File

@@ -14,9 +14,9 @@ export class AuthManager extends AbstractService implements AuthClientInterface
super(internalEventBus)
}
async generateRecoveryCodes(): Promise<string | false> {
async generateRecoveryCodes(dto: { serverPassword: string }): Promise<string | false> {
try {
const result = await this.authApiService.generateRecoveryCodes()
const result = await this.authApiService.generateRecoveryCodes(dto)
if (isErrorResponse(result)) {
return false

View File

@@ -1,6 +1,6 @@
import { ApplicationServiceInterface } from './../Service/ApplicationServiceInterface'
import { DecryptedItem, DecryptedItemInterface, FileItem, SNNote } from '@standardnotes/models'
import { ChallengeInterface, ChallengeReason } from '../Challenge'
import { ChallengeInterface, ChallengeReason, ChallengeResponseInterface } from '../Challenge'
import { MobileUnlockTiming } from './MobileUnlockTiming'
import { TimingDisplayOption } from './TimingDisplayOption'
import { ProtectionEvent } from './ProtectionEvent'
@@ -28,6 +28,10 @@ export interface ProtectionsClientInterface extends ApplicationServiceInterface<
reason: ChallengeReason,
dto: { fallBackToAccountPassword: boolean; requireAccountPassword: boolean; forcePrompt: boolean },
): Promise<boolean>
authorizeActionWithChallengeResponse(
reason: ChallengeReason,
dto: { fallBackToAccountPassword: boolean; requireAccountPassword: boolean; forcePrompt: boolean },
): Promise<{ success: boolean; challengeResponse?: ChallengeResponseInterface }>
authorizeAddingPasscode(): Promise<boolean>
authorizeRemovingPasscode(): Promise<boolean>
authorizeChangingPasscode(): Promise<boolean>
@@ -36,7 +40,8 @@ export interface ProtectionsClientInterface extends ApplicationServiceInterface<
authorizeAutolockIntervalChange(): Promise<boolean>
authorizeSearchingProtectedNotesText(): Promise<boolean>
authorizeBackupCreation(): Promise<boolean>
authorizeMfaDisable(): Promise<boolean>
authorizeMfaDisable(): Promise<{ success: boolean; challengeResponse?: ChallengeResponseInterface }>
authorizeAccountDeletion(): Promise<{ success: boolean; challengeResponse?: ChallengeResponseInterface }>
protectItems<I extends DecryptedItemInterface>(items: I[]): Promise<I[]>
unprotectItems<I extends DecryptedItemInterface>(items: I[], reason: ChallengeReason): Promise<I[] | undefined>

View File

@@ -237,13 +237,9 @@ export class UserService
error: boolean
message?: string
}> {
if (
!(await this.protections.authorizeAction(ChallengeReason.DeleteAccount, {
fallBackToAccountPassword: true,
requireAccountPassword: true,
forcePrompt: false,
}))
) {
const { success, challengeResponse } = await this.protections.authorizeAccountDeletion()
if (!success) {
return {
error: true,
message: Messages.INVALID_PASSWORD,
@@ -251,7 +247,13 @@ export class UserService
}
const uuid = this.sessions.getSureUser().uuid
const response = await this.userApi.deleteAccount(uuid)
const password = challengeResponse?.getValueForType(ChallengeValidation.AccountPassword).value as string
const currentRootKey = await this.encryption.computeRootKey(
password,
this.encryption.getRootKeyParams() as SNRootKeyParams,
)
const serverPassword = currentRootKey.serverPassword
const response = await this.userApi.deleteAccount({ userUuid: uuid, serverPassword: serverPassword })
if (isErrorResponse(response)) {
return {
error: true,