From fd4036f0c804c9ff860fb349a3606f4836a4a34f Mon Sep 17 00:00:00 2001 From: MaysWind Date: Sun, 26 Oct 2025 15:18:40 +0800 Subject: [PATCH] verify passcode on the OAuth 2.0 callback page if user enable 2FA --- pkg/api/authorizations.go | 29 ++++++++++++++++++++++++ pkg/errs/twofactor_authorization.go | 1 + pkg/models/oauth2.go | 1 + src/consts/api.ts | 1 + src/locales/de.json | 1 + src/locales/en.json | 1 + src/locales/es.json | 1 + src/locales/fr.json | 1 + src/locales/it.json | 1 + src/locales/ja.json | 1 + src/locales/ko.json | 1 + src/locales/nl.json | 1 + src/locales/pt_BR.json | 1 + src/locales/ru.json | 1 + src/locales/th.json | 1 + src/locales/uk.json | 1 + src/locales/vi.json | 1 + src/locales/zh_Hans.json | 1 + src/locales/zh_Hant.json | 1 + src/models/oauth2.ts | 1 + src/stores/index.ts | 5 ++-- src/views/desktop/OAuth2CallbackPage.vue | 24 ++++++++++++++++++-- 22 files changed, 73 insertions(+), 4 deletions(-) diff --git a/pkg/api/authorizations.go b/pkg/api/authorizations.go index 915bcf05..9717f51d 100644 --- a/pkg/api/authorizations.go +++ b/pkg/api/authorizations.go @@ -2,6 +2,7 @@ package api import ( "encoding/json" + "errors" "github.com/pquerna/otp/totp" @@ -427,6 +428,34 @@ func (a *AuthorizationsApi) OAuth2CallbackAuthorizeHandler(c *core.WebContext) ( return nil, errs.ErrUserPasswordWrong } + if a.CurrentConfig().EnableTwoFactor { + twoFactorSetting, err := a.twoFactorAuthorizations.GetUserTwoFactorSettingByUid(c, uid) + + if err != nil && !errors.Is(err, errs.ErrTwoFactorIsNotEnabled) { + log.Errorf(c, "[authorizations.OAuth2CallbackAuthorizeHandler] failed to check two-factor setting for user \"uid:%d\", because %s", user.Uid, err.Error()) + return nil, errs.Or(err, errs.ErrSystemError) + } + + if twoFactorSetting != nil { + if credential.Passcode == "" { + return nil, errs.ErrPasscodeEmpty + } + + if !totp.Validate(credential.Passcode, twoFactorSetting.Secret) { + log.Warnf(c, "[authorizations.OAuth2CallbackAuthorizeHandler] passcode is invalid for user \"uid:%d\"", uid) + + err = a.CheckAndIncreaseFailureCount(c, uid) + + if err != nil { + log.Warnf(c, "[authorizations.OAuth2CallbackAuthorizeHandler] cannot auth for user \"uid:%d\", because %s", uid, err.Error()) + return nil, errs.Or(err, errs.ErrFailureCountLimitReached) + } + + return nil, errs.ErrPasscodeInvalid + } + } + } + userExternalAuth := &models.UserExternalAuth{ Uid: user.Uid, ExternalAuthType: tokenContext.ExternalAuthType, diff --git a/pkg/errs/twofactor_authorization.go b/pkg/errs/twofactor_authorization.go index 96646d80..8a7bad75 100644 --- a/pkg/errs/twofactor_authorization.go +++ b/pkg/errs/twofactor_authorization.go @@ -9,4 +9,5 @@ var ( ErrTwoFactorRecoveryCodeNotExist = NewNormalError(NormalSubcategoryTwofactor, 2, http.StatusUnauthorized, "two-factor backup code does not exist") ErrTwoFactorIsNotEnabled = NewNormalError(NormalSubcategoryTwofactor, 3, http.StatusBadRequest, "two-factor is not enabled") ErrTwoFactorAlreadyEnabled = NewNormalError(NormalSubcategoryTwofactor, 4, http.StatusBadRequest, "two-factor has already been enabled") + ErrPasscodeEmpty = NewNormalError(NormalSubcategoryTwofactor, 5, http.StatusUnauthorized, "passcode is empty") ) diff --git a/pkg/models/oauth2.go b/pkg/models/oauth2.go index 6954bc36..f1667154 100644 --- a/pkg/models/oauth2.go +++ b/pkg/models/oauth2.go @@ -17,4 +17,5 @@ type OAuth2CallbackRequest struct { // OAuth2CallbackLoginRequest represents all parameters of OAuth 2.0 callback login request type OAuth2CallbackLoginRequest struct { Password string `json:"password" binding:"omitempty,min=6,max=128"` + Passcode string `json:"passcode" binding:"omitempty,notBlank,len=6"` } diff --git a/src/consts/api.ts b/src/consts/api.ts index 1e2d0bd5..115de41d 100644 --- a/src/consts/api.ts +++ b/src/consts/api.ts @@ -18,6 +18,7 @@ export enum KnownErrorCode { ApiNotFound = 100001, ValidatorError = 200000, UserEmailNotVerified = 201020, + TwoFactorAuthorizationPasscodeEmpty = 203005, TransactionCannotCreateInThisTime = 205017, TransactionCannotModifyInThisTime = 205018, TransactionPictureNotFound = 211001 diff --git a/src/locales/de.json b/src/locales/de.json index 789c284b..92dcad0a 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -1110,6 +1110,7 @@ "two-factor is not enabled": "Zwei-Faktor-Authentifizierung ist nicht aktiviert", "two-factor has already been enabled": "Zwei-Faktor-Authentifizierung ist bereits aktiviert", "two-factor backup code does not exist": "Zwei-Faktor-Backup-Code existiert nicht", + "passcode is empty": "Passcode is empty", "account id is invalid": "Konto-ID ist ungültig", "account not found": "Konto nicht gefunden", "account type is invalid": "Kontotyp ist ungültig", diff --git a/src/locales/en.json b/src/locales/en.json index 50419b44..c1059cab 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1110,6 +1110,7 @@ "two-factor is not enabled": "Two-factor is not enabled", "two-factor has already been enabled": "Two-factor has already been enabled", "two-factor backup code does not exist": "Two-factor backup code does not exist", + "passcode is empty": "Passcode is empty", "account id is invalid": "Account ID is invalid", "account not found": "Account is not found", "account type is invalid": "Account type is invalid", diff --git a/src/locales/es.json b/src/locales/es.json index 97857298..d3521d58 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -1110,6 +1110,7 @@ "two-factor is not enabled": "El doble factor no está habilitado", "two-factor has already been enabled": "Ya se ha habilitado el doble factor", "two-factor backup code does not exist": "El código de respaldo de dos factores no existe", + "passcode is empty": "Passcode is empty", "account id is invalid": "El ID de cuenta no es válido", "account not found": "No se encuentra la cuenta", "account type is invalid": "El tipo de cuenta no es válido", diff --git a/src/locales/fr.json b/src/locales/fr.json index 9e276df8..0310cb46 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -1110,6 +1110,7 @@ "two-factor is not enabled": "L'authentification à deux facteurs n'est pas activée", "two-factor has already been enabled": "L'authentification à deux facteurs a déjà été activée", "two-factor backup code does not exist": "Le code de sauvegarde à deux facteurs n'existe pas", + "passcode is empty": "Passcode is empty", "account id is invalid": "L'ID du compte est invalide", "account not found": "Compte non trouvé", "account type is invalid": "Le type de compte est invalide", diff --git a/src/locales/it.json b/src/locales/it.json index 3459b162..5e364320 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -1110,6 +1110,7 @@ "two-factor is not enabled": "L'autenticazione a due fattori non è abilitata", "two-factor has already been enabled": "L'autenticazione a due fattori è già abilitata", "two-factor backup code does not exist": "Il codice di backup a due fattori non esiste", + "passcode is empty": "Passcode is empty", "account id is invalid": "ID conto non valido", "account not found": "Conto non trovato", "account type is invalid": "Tipo di conto non valido", diff --git a/src/locales/ja.json b/src/locales/ja.json index b2a3e1ef..3bf4e355 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -1110,6 +1110,7 @@ "two-factor is not enabled": "二要素が有効になっていません", "two-factor has already been enabled": "二要素はすでに有効になっています", "two-factor backup code does not exist": "二要素バックアップコードが存在しません", + "passcode is empty": "Passcode is empty", "account id is invalid": "口座IDは無効です", "account not found": "口座が見つかりません", "account type is invalid": "口座タイプは無効です", diff --git a/src/locales/ko.json b/src/locales/ko.json index 9100726c..937b0d3d 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -1110,6 +1110,7 @@ "two-factor is not enabled": "2단계 인증이 활성화되지 않았습니다", "two-factor has already been enabled": "2단계 인증이 이미 활성화되었습니다", "two-factor backup code does not exist": "2단계 백업 코드가 존재하지 않습니다", + "passcode is empty": "Passcode is empty", "account id is invalid": "계좌 ID가 유효하지 않습니다", "account not found": "계좌를 찾을 수 없습니다", "account type is invalid": "계좌 유형이 유효하지 않습니다", diff --git a/src/locales/nl.json b/src/locales/nl.json index 3cf4e7ae..9952d6c5 100644 --- a/src/locales/nl.json +++ b/src/locales/nl.json @@ -1110,6 +1110,7 @@ "two-factor is not enabled": "Twee-stapsverificatie is niet ingeschakeld", "two-factor has already been enabled": "Twee-stapsverificatie is al ingeschakeld", "two-factor backup code does not exist": "Back-upcode voor twee-stapsverificatie bestaat niet", + "passcode is empty": "Passcode is empty", "account id is invalid": "Rekening-ID is ongeldig", "account not found": "Rekening niet gevonden", "account type is invalid": "Rekeningtype is ongeldig", diff --git a/src/locales/pt_BR.json b/src/locales/pt_BR.json index 3c5155e4..d52e87a7 100644 --- a/src/locales/pt_BR.json +++ b/src/locales/pt_BR.json @@ -1110,6 +1110,7 @@ "two-factor is not enabled": "Autenticação em duas etapas não está ativada", "two-factor has already been enabled": "Autenticação em duas etapas já foi ativada", "two-factor backup code does not exist": "Código de backup de duas etapas não existe", + "passcode is empty": "Passcode is empty", "account id is invalid": "ID da conta é inválido", "account not found": "Conta não encontrada", "account type is invalid": "Tipo de conta é inválido", diff --git a/src/locales/ru.json b/src/locales/ru.json index c542757f..2b21e1f8 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -1110,6 +1110,7 @@ "two-factor is not enabled": "Двухфакторная аутентификация не включена", "two-factor has already been enabled": "Двухфакторная аутентификация уже включена", "two-factor backup code does not exist": "Резервный код двухфакторной аутентификации не существует", + "passcode is empty": "Passcode is empty", "account id is invalid": "ID счета недействителен", "account not found": "Счет не найден", "account type is invalid": "Тип счета недействителен", diff --git a/src/locales/th.json b/src/locales/th.json index 1067be19..2958925f 100644 --- a/src/locales/th.json +++ b/src/locales/th.json @@ -1110,6 +1110,7 @@ "two-factor is not enabled": "ยังไม่ได้เปิดใช้งานการยืนยันสองขั้นตอน", "two-factor has already been enabled": "การยืนยันสองขั้นตอนถูกเปิดใช้งานแล้ว", "two-factor backup code does not exist": "รหัสสำรองสองขั้นตอนไม่พบ", + "passcode is empty": "Passcode is empty", "account id is invalid": "รหัสบัญชีไม่ถูกต้อง", "account not found": "ไม่พบบัญชี", "account type is invalid": "ประเภทบัญชีไม่ถูกต้อง", diff --git a/src/locales/uk.json b/src/locales/uk.json index e6062325..4e76be2d 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -1110,6 +1110,7 @@ "two-factor is not enabled": "Двофакторна автентифікація не увімкнена", "two-factor has already been enabled": "Двофакторна автентифікація вже увімкнена", "two-factor backup code does not exist": "Резервного коду двофакторної автентифікації не існує", + "passcode is empty": "Passcode is empty", "account id is invalid": "ID рахунку недійсний", "account not found": "Рахунок не знайдено", "account type is invalid": "Тип рахунку недійсний", diff --git a/src/locales/vi.json b/src/locales/vi.json index 0dcca923..6b100f96 100644 --- a/src/locales/vi.json +++ b/src/locales/vi.json @@ -1110,6 +1110,7 @@ "two-factor is not enabled": "Xác thực hai yếu tố chưa được bật", "two-factor has already been enabled": "Xác thực hai yếu tố đã được bật", "two-factor backup code does not exist": "Mã sao lưu hai yếu tố không tồn tại", + "passcode is empty": "Passcode is empty", "account id is invalid": "ID tài khoản không hợp lệ", "account not found": "Không tìm thấy tài khoản", "account type is invalid": "Loại tài khoản không hợp lệ", diff --git a/src/locales/zh_Hans.json b/src/locales/zh_Hans.json index d7f2e985..356f3655 100644 --- a/src/locales/zh_Hans.json +++ b/src/locales/zh_Hans.json @@ -1110,6 +1110,7 @@ "two-factor is not enabled": "两步验证没有启用", "two-factor has already been enabled": "两步验证已经启用", "two-factor backup code does not exist": "两步验证备用码不存在", + "passcode is empty": "验证码为空", "account id is invalid": "账户ID无效", "account not found": "账户不存在", "account type is invalid": "账户类型无效", diff --git a/src/locales/zh_Hant.json b/src/locales/zh_Hant.json index 5c73a97a..36476037 100644 --- a/src/locales/zh_Hant.json +++ b/src/locales/zh_Hant.json @@ -1110,6 +1110,7 @@ "two-factor is not enabled": "二步驟驗證沒有啟用", "two-factor has already been enabled": "二步驟驗證已經啟用", "two-factor backup code does not exist": "二步驟驗證備用碼不存在", + "passcode is empty": "驗證碼為空", "account id is invalid": "帳戶ID無效", "account not found": "帳戶不存在", "account type is invalid": "帳戶類型無效", diff --git a/src/models/oauth2.ts b/src/models/oauth2.ts index 6beae1e4..ddb65684 100644 --- a/src/models/oauth2.ts +++ b/src/models/oauth2.ts @@ -1,3 +1,4 @@ export interface OAuth2CallbackLoginRequest { readonly password?: string; + readonly passcode?: string; } diff --git a/src/stores/index.ts b/src/stores/index.ts index 06276801..06d856bd 100644 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -191,11 +191,12 @@ export const useRootStore = defineStore('root', () => { }); } - function authorizeOAuth2({ password, token }: { password?: string, token: string }): Promise { + function authorizeOAuth2({ password, passcode, token }: { password?: string, passcode?: string, token: string }): Promise { return new Promise((resolve, reject) => { services.authorizeOAuth2({ req: { - password + password, + passcode }, token }).then(response => { diff --git a/src/views/desktop/OAuth2CallbackPage.vue b/src/views/desktop/OAuth2CallbackPage.vue index cef380e3..7c640355 100644 --- a/src/views/desktop/OAuth2CallbackPage.vue +++ b/src/views/desktop/OAuth2CallbackPage.vue @@ -39,7 +39,7 @@ type="password" autocomplete="password" :autofocus="true" - :disabled="loggingInByOAuth2" + :disabled="show2faInput || loggingInByOAuth2" :label="tt('Password')" :placeholder="tt('Your password')" v-model="password" @@ -47,6 +47,19 @@ /> + + + + {{ tt('Continue') }} @@ -97,7 +110,7 @@