zitadel/internal/api/ui/login/mfa_prompt_handler.go
Livio Amstutz 2c4799c223
feat: complete dynamic domain handling (#3482)
* feat: dynamic issuer

* feat: default language from context

* remove zitadel docs from defaults

* remove ConsoleOverwriteDir

* remove notification endpoints from defaults

* custom domains in emails

* remove (external) domain

* external domain completely removed, console handling fixed

* fix test

* fix defaults.yaml
2022-04-25 11:16:36 +02:00

106 lines
2.9 KiB
Go

package login
import (
"net/http"
"github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors"
)
const (
tmplMFAPrompt = "mfaprompt"
)
type mfaPromptData struct {
MFAProvider domain.MFAType `schema:"provider"`
Skip bool `schema:"skip"`
}
func (l *Login) handleMFAPrompt(w http.ResponseWriter, r *http.Request) {
data := new(mfaPromptData)
authReq, err := l.getAuthRequestAndParseData(r, data)
if err != nil {
l.renderError(w, r, authReq, err)
return
}
if !data.Skip {
mfaVerifyData := new(mfaVerifyData)
mfaVerifyData.MFAType = data.MFAProvider
l.handleMFACreation(w, r, authReq, mfaVerifyData)
return
}
err = l.command.HumanSkipMFAInit(setContext(r.Context(), authReq.UserOrgID), authReq.UserID, authReq.UserOrgID)
if err != nil {
l.renderError(w, r, authReq, err)
return
}
l.handleLogin(w, r)
}
func (l *Login) handleMFAPromptSelection(w http.ResponseWriter, r *http.Request) {
data := new(mfaPromptData)
authReq, err := l.getAuthRequestAndParseData(r, data)
if err != nil {
l.renderError(w, r, authReq, err)
return
}
l.renderNextStep(w, r, authReq)
}
func (l *Login) renderMFAPrompt(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, mfaPromptData *domain.MFAPromptStep, err error) {
var errID, errMessage string
if err != nil {
errID, errMessage = l.getErrorMessage(r, err)
}
data := mfaData{
baseData: l.getBaseData(r, authReq, "MFA Prompt", errID, errMessage),
profileData: l.getProfileData(authReq),
}
if mfaPromptData == nil {
l.renderError(w, r, authReq, caos_errs.ThrowPreconditionFailed(nil, "APP-XU0tj", "Errors.User.MFA.NoProviders"))
return
}
data.MFAProviders = mfaPromptData.MFAProviders
data.MFARequired = mfaPromptData.Required
if len(mfaPromptData.MFAProviders) == 1 && mfaPromptData.Required {
data := &mfaVerifyData{
MFAType: mfaPromptData.MFAProviders[0],
}
l.handleMFACreation(w, r, authReq, data)
return
}
translator := l.getTranslator(r.Context(), authReq)
l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplMFAPrompt], data, nil)
}
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)
return
case domain.MFATypeU2F:
l.renderRegisterU2F(w, r, authReq, nil)
return
}
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)
if err != nil {
l.renderError(w, r, authReq, err)
return
}
data.otpData = otpData{
Secret: otp.SecretString,
Url: otp.Url,
}
l.renderMFAInitVerify(w, r, authReq, data, nil)
}