diff --git a/api/user/otp.go b/api/user/otp.go index 108a5f4a..66071ea6 100644 --- a/api/user/otp.go +++ b/api/user/otp.go @@ -3,9 +3,11 @@ package user import ( "bytes" "crypto/sha1" - "encoding/base64" "encoding/hex" "fmt" + "net/http" + "strings" + "github.com/0xJacky/Nginx-UI/api" "github.com/0xJacky/Nginx-UI/internal/crypto" "github.com/0xJacky/Nginx-UI/query" @@ -14,9 +16,6 @@ import ( "github.com/pquerna/otp" "github.com/pquerna/otp/totp" "github.com/uozi-tech/cosy" - "image/jpeg" - "net/http" - "strings" ) func GenerateTOTP(c *gin.Context) { @@ -38,27 +37,9 @@ func GenerateTOTP(c *gin.Context) { return } - qrCode, err := otpKey.Image(512, 512) - if err != nil { - api.ErrHandler(c, err) - return - } - - // Encode the image to a buffer - var buf []byte - buffer := bytes.NewBuffer(buf) - err = jpeg.Encode(buffer, qrCode, nil) - if err != nil { - fmt.Println("Error encoding image:", err) - return - } - - // Convert the buffer to a base64 string - base64Str := "data:image/jpeg;base64," + base64.StdEncoding.EncodeToString(buffer.Bytes()) - c.JSON(http.StatusOK, gin.H{ - "secret": otpKey.Secret(), - "qr_code": base64Str, + "secret": otpKey.Secret(), + "url": otpKey.URL(), }) } diff --git a/app/components.d.ts b/app/components.d.ts index 644e4f40..7defeaea 100644 --- a/app/components.d.ts +++ b/app/components.d.ts @@ -49,6 +49,7 @@ declare module 'vue' { APopconfirm: typeof import('ant-design-vue/es')['Popconfirm'] APopover: typeof import('ant-design-vue/es')['Popover'] AProgress: typeof import('ant-design-vue/es')['Progress'] + AQrcode: typeof import('ant-design-vue/es')['QRCode'] ARadioButton: typeof import('ant-design-vue/es')['RadioButton'] ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup'] AResult: typeof import('ant-design-vue/es')['Result'] diff --git a/app/src/api/otp.ts b/app/src/api/otp.ts index 75672a0b..0bbe2c63 100644 --- a/app/src/api/otp.ts +++ b/app/src/api/otp.ts @@ -2,7 +2,7 @@ import http from '@/lib/http' export interface OTPGenerateSecretResponse { secret: string - qr_code: string + url: string } const otp = { diff --git a/app/src/views/preference/components/TOTP.vue b/app/src/views/preference/components/TOTP.vue index 36a1cbba..b8d55141 100644 --- a/app/src/views/preference/components/TOTP.vue +++ b/app/src/views/preference/components/TOTP.vue @@ -10,7 +10,7 @@ import { message } from 'ant-design-vue' const status = ref(false) const enrolling = ref(false) const resetting = ref(false) -const qrCode = ref('') +const generatedUrl = ref('') const secret = ref('') const passcode = ref('') const refOtp = useTemplateRef('refOtp') @@ -25,7 +25,7 @@ function clickEnable2FA() { function generateSecret() { otp.generate_secret().then(r => { secret.value = r.secret - qrCode.value = r.qr_code + generatedUrl.value = r.url refOtp.value?.clearInput() }) } @@ -70,9 +70,7 @@ function reset2FA() {
{{ $gettext('TOTP is a two-factor authentication method that uses a time-based one-time password algorithm.') }}
{{ $gettext('To enable it, you need to install the Google or Microsoft Authenticator app on your mobile phone.') }}
{{ $gettext('Scan the QR code with your mobile phone to add the account to the app.') }}
-- {{ $gettext('Current account is not enabled TOTP.') }} -
+{{ $gettext('Input the code from the app:') }}
-{{ $gettext('Input the code from the app:') }}
+