mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 01:47:33 +00:00
feat(api): add and remove OTP (SMS and email) (#6295)
* refactor: rename otp to totp * feat: add otp sms and email * implement tests
This commit is contained in:
@@ -33,7 +33,7 @@ func (l *Login) handleMFAInitVerify(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
var verifyData *mfaVerifyData
|
||||
switch data.MFAType {
|
||||
case domain.MFATypeOTP:
|
||||
case domain.MFATypeTOTP:
|
||||
verifyData = l.handleOTPVerify(w, r, authReq, data)
|
||||
}
|
||||
|
||||
@@ -50,13 +50,13 @@ func (l *Login) handleMFAInitVerify(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (l *Login) handleOTPVerify(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, data *mfaInitVerifyData) *mfaVerifyData {
|
||||
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
|
||||
_, err := l.command.HumanCheckMFAOTPSetup(setContext(r.Context(), authReq.UserOrgID), authReq.UserID, data.Code, userAgentID, authReq.UserOrgID)
|
||||
_, err := l.command.HumanCheckMFATOTPSetup(setContext(r.Context(), authReq.UserOrgID), authReq.UserID, data.Code, userAgentID, authReq.UserOrgID)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
mfadata := &mfaVerifyData{
|
||||
MFAType: data.MFAType,
|
||||
otpData: otpData{
|
||||
totpData: totpData{
|
||||
Secret: data.Secret,
|
||||
Url: data.URL,
|
||||
},
|
||||
@@ -73,10 +73,10 @@ func (l *Login) renderMFAInitVerify(w http.ResponseWriter, r *http.Request, auth
|
||||
translator := l.getTranslator(r.Context(), authReq)
|
||||
data.baseData = l.getBaseData(r, authReq, "InitMFAOTP.Title", "InitMFAOTP.Description", errID, errMessage)
|
||||
data.profileData = l.getProfileData(authReq)
|
||||
if data.MFAType == domain.MFATypeOTP {
|
||||
code, err := generateQrCode(data.otpData.Url)
|
||||
if data.MFAType == domain.MFATypeTOTP {
|
||||
code, err := generateQrCode(data.totpData.Url)
|
||||
if err == nil {
|
||||
data.otpData.QrCode = code
|
||||
data.totpData.QrCode = code
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -80,8 +80,8 @@ func (l *Login) renderMFAPrompt(w http.ResponseWriter, r *http.Request, authReq
|
||||
|
||||
func (l *Login) handleMFACreation(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, data *mfaVerifyData) {
|
||||
switch data.MFAType {
|
||||
case domain.MFATypeOTP:
|
||||
l.handleOTPCreation(w, r, authReq, data)
|
||||
case domain.MFATypeTOTP:
|
||||
l.handleTOTPCreation(w, r, authReq, data)
|
||||
return
|
||||
case domain.MFATypeU2F:
|
||||
l.renderRegisterU2F(w, r, authReq, nil)
|
||||
@@ -90,16 +90,16 @@ func (l *Login) handleMFACreation(w http.ResponseWriter, r *http.Request, authRe
|
||||
l.renderError(w, r, authReq, caos_errs.ThrowPreconditionFailed(nil, "APP-Or3HO", "Errors.User.MFA.NoProviders"))
|
||||
}
|
||||
|
||||
func (l *Login) handleOTPCreation(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, data *mfaVerifyData) {
|
||||
otp, err := l.command.AddHumanOTP(setContext(r.Context(), authReq.UserOrgID), authReq.UserID, authReq.UserOrgID)
|
||||
func (l *Login) handleTOTPCreation(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, data *mfaVerifyData) {
|
||||
otp, err := l.command.AddHumanTOTP(setContext(r.Context(), authReq.UserOrgID), authReq.UserID, authReq.UserOrgID)
|
||||
if err != nil {
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
|
||||
data.otpData = otpData{
|
||||
Secret: otp.SecretString,
|
||||
Url: otp.Url,
|
||||
data.totpData = totpData{
|
||||
Secret: otp.Secret,
|
||||
Url: otp.URI,
|
||||
}
|
||||
l.renderMFAInitVerify(w, r, authReq, data, nil)
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@ func (l *Login) handleMFAVerify(w http.ResponseWriter, r *http.Request) {
|
||||
l.renderMFAVerifySelected(w, r, authReq, step, data.SelectedProvider, nil)
|
||||
return
|
||||
}
|
||||
if data.MFAType == domain.MFATypeOTP {
|
||||
if data.MFAType == domain.MFATypeTOTP {
|
||||
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
|
||||
err = l.authRepo.VerifyMFAOTP(setContext(r.Context(), authReq.UserOrgID), authReq.ID, authReq.UserID, authReq.UserOrgID, data.Code, userAgentID, domain.BrowserInfoFromRequest(r))
|
||||
|
||||
@@ -45,7 +45,7 @@ func (l *Login) handleMFAVerify(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
l.renderMFAVerifySelected(w, r, authReq, step, domain.MFATypeOTP, err)
|
||||
l.renderMFAVerifySelected(w, r, authReq, step, domain.MFATypeTOTP, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -79,9 +79,9 @@ func (l *Login) renderMFAVerifySelected(w http.ResponseWriter, r *http.Request,
|
||||
data.Description = translator.LocalizeWithoutArgs("VerifyMFAU2F.Description")
|
||||
l.renderU2FVerification(w, r, authReq, removeSelectedProviderFromList(verificationStep.MFAProviders, domain.MFATypeU2F), nil)
|
||||
return
|
||||
case domain.MFATypeOTP:
|
||||
data.MFAProviders = removeSelectedProviderFromList(verificationStep.MFAProviders, domain.MFATypeOTP)
|
||||
data.SelectedMFAProvider = domain.MFATypeOTP
|
||||
case domain.MFATypeTOTP:
|
||||
data.MFAProviders = removeSelectedProviderFromList(verificationStep.MFAProviders, domain.MFATypeTOTP)
|
||||
data.SelectedMFAProvider = domain.MFATypeTOTP
|
||||
data.Title = translator.LocalizeWithoutArgs("VerifyMFAOTP.Title")
|
||||
data.Description = translator.LocalizeWithoutArgs("VerifyMFAOTP.Description")
|
||||
default:
|
||||
|
@@ -673,7 +673,7 @@ type mfaVerifyData struct {
|
||||
baseData
|
||||
profileData
|
||||
MFAType domain.MFAType
|
||||
otpData
|
||||
totpData
|
||||
}
|
||||
|
||||
type mfaDoneData struct {
|
||||
@@ -682,7 +682,7 @@ type mfaDoneData struct {
|
||||
MFAType domain.MFAType
|
||||
}
|
||||
|
||||
type otpData struct {
|
||||
type totpData struct {
|
||||
Url string
|
||||
Secret string
|
||||
QrCode string
|
||||
|
Reference in New Issue
Block a user