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:
Livio Spring
2023-08-02 18:57:53 +02:00
committed by GitHub
parent ca13e70c92
commit a1942ecdaa
44 changed files with 2253 additions and 215 deletions

View File

@@ -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
}
}

View File

@@ -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)
}

View File

@@ -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:

View File

@@ -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