Skip to content

Commit

Permalink
fix(core): totp already enabled (#4607)
Browse files Browse the repository at this point in the history
  • Loading branch information
dolcalmi authored Oct 5, 2024
1 parent f760861 commit 52e7cea
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 0 deletions.
5 changes: 5 additions & 0 deletions bats/core/api/auth.bats
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,11 @@ generateTotpCode() {
# Checking the response structure
totpEnabled="$(graphql_output '.data.userTotpRegistrationValidate.me.totpEnabled')"
[ "$totpEnabled" == "true" ] || exit 1

exec_graphql 'charlie' 'user-totp-registration-initiate'
error_message="$(graphql_output '.data.userTotpRegistrationInitiate.errors[0].message')"
expected_message="TOTP has already been enabled for this account. If you need to reset it, please contact support."
[[ "$error_message" == "$expected_message" ]] || exit 1
}

@test "auth: log in with email with totp activated" {
Expand Down
6 changes: 6 additions & 0 deletions core/api/src/app/authentication/totp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import {
AuthTokenUserIdMismatchError,
IdentifierNotFoundError,
} from "@/domain/authentication/errors"
import { TotpAlreadyExistsError } from "@/domain/kratos"
import {
AuthWithEmailPasswordlessService,
AuthWithPhonePasswordlessService,
IdentityRepository,
kratosElevatingSessionWithTotp,
kratosInitiateTotp,
kratosRemoveTotp,
Expand All @@ -26,6 +28,10 @@ export const initiateTotpRegistration = async ({
}: {
userId: UserId
}): Promise<InitiateTotpRegistrationResult | KratosError> => {
const identity = await IdentityRepository().getIdentity(userId)
if (identity instanceof Error) return identity
if (identity.totpEnabled) return new TotpAlreadyExistsError()

const authToken = await getAuthTokenFromUserId(userId)
if (authToken instanceof Error) {
return authToken
Expand Down
1 change: 1 addition & 0 deletions core/api/src/domain/kratos/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export class InvalidIdentitySessionKratosError extends KratosError {}
export class SessionRefreshRequiredError extends KratosError {}

export class EmailAlreadyExistsError extends KratosError {}
export class TotpAlreadyExistsError extends KratosError {}

export class PhoneAccountAlreadyExistsError extends KratosError {
level = ErrorLevel.Info
Expand Down
4 changes: 4 additions & 0 deletions core/api/src/graphql/error-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
AccountAlreadyHasEmailError,
PhoneAlreadyExistsError,
EmailAlreadyExistsError,
TotpAlreadyExistsError,
SessionRefreshRequiredError,
CodeExpiredError,
UnauthorizedIPForOnboardingError,
Expand Down Expand Up @@ -491,6 +492,9 @@ export const mapError = (error: ApplicationError): CustomGraphQLError => {
case "EmailAlreadyExistsError":
return new EmailAlreadyExistsError({ logger: baseLogger })

case "TotpAlreadyExistsError":
return new TotpAlreadyExistsError({ logger: baseLogger })

case "CodeExpiredKratosError":
return new CodeExpiredError({ logger: baseLogger })

Expand Down
12 changes: 12 additions & 0 deletions core/api/src/graphql/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,18 @@ export class EmailAlreadyExistsError extends CustomGraphQLError {
}
}

export class TotpAlreadyExistsError extends CustomGraphQLError {
constructor(errData: CustomGraphQLErrorData) {
super({
message:
"TOTP has already been enabled for this account. If you need to reset it, please contact support.",
forwardToClient: true,
code: "TOTP_ACCOUNT_ALREADY_EXISTS_ERROR",
...errData,
})
}
}

export class CodeExpiredError extends CustomGraphQLError {
constructor(errData: CustomGraphQLErrorData) {
super({
Expand Down

0 comments on commit 52e7cea

Please sign in to comment.