forked from zitadel/zitadel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mfa_prompt_handler.go
105 lines (90 loc) · 2.93 KB
/
mfa_prompt_handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package login
import (
"net/http"
"github.com/dennigogo/zitadel/internal/domain"
caos_errs "github.com/dennigogo/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)
}