-
Notifications
You must be signed in to change notification settings - Fork 28
/
settings_totp.go
124 lines (105 loc) · 3.21 KB
/
settings_totp.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package webapp
import (
"net/http"
"github.com/authgear/authgear-server/pkg/api/model"
"github.com/authgear/authgear-server/pkg/auth/handler/webapp/viewmodels"
"github.com/authgear/authgear-server/pkg/auth/webapp"
"github.com/authgear/authgear-server/pkg/lib/authn"
"github.com/authgear/authgear-server/pkg/lib/authn/authenticator"
"github.com/authgear/authgear-server/pkg/lib/interaction/intents"
"github.com/authgear/authgear-server/pkg/lib/session"
"github.com/authgear/authgear-server/pkg/util/httproute"
"github.com/authgear/authgear-server/pkg/util/httputil"
"github.com/authgear/authgear-server/pkg/util/template"
)
var TemplateWebSettingsTOTPHTML = template.RegisterHTML(
"web/settings_totp.html",
Components...,
)
func ConfigureSettingsTOTPRoute(route httproute.Route) httproute.Route {
return route.
WithMethods("OPTIONS", "POST", "GET").
WithPathPattern("/settings/mfa/totp")
}
type SettingsTOTPViewModel struct {
Authenticators []*authenticator.Info
}
type SettingsTOTPHandler struct {
ControllerFactory ControllerFactory
BaseViewModel *viewmodels.BaseViewModeler
Renderer Renderer
Authenticators SettingsAuthenticatorService
}
func (h *SettingsTOTPHandler) GetData(r *http.Request, rw http.ResponseWriter) (map[string]interface{}, error) {
data := map[string]interface{}{}
baseViewModel := h.BaseViewModel.ViewModel(r, rw)
userID := session.GetUserID(r.Context())
viewModel := SettingsTOTPViewModel{}
authenticators, err := h.Authenticators.List(*userID,
authenticator.KeepKind(authenticator.KindSecondary),
authenticator.KeepType(model.AuthenticatorTypeTOTP),
)
if err != nil {
return nil, err
}
viewModel.Authenticators = authenticators
viewmodels.Embed(data, baseViewModel)
viewmodels.Embed(data, viewModel)
return data, nil
}
func (h *SettingsTOTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctrl, err := h.ControllerFactory.New(r, w)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
defer ctrl.Serve()
redirectURI := httputil.HostRelative(r.URL).String()
authenticatorID := r.Form.Get("x_authenticator_id")
userID := ctrl.RequireUserID()
ctrl.Get(func() error {
data, err := h.GetData(r, w)
if err != nil {
return err
}
h.Renderer.RenderHTML(w, r, TemplateWebSettingsTOTPHTML, data)
return nil
})
ctrl.PostAction("remove", func() error {
opts := webapp.SessionOptions{
RedirectURI: redirectURI,
}
intent := intents.NewIntentRemoveAuthenticator(userID)
result, err := ctrl.EntryPointPost(opts, intent, func() (input interface{}, err error) {
input = &InputRemoveAuthenticator{
Type: model.AuthenticatorTypeTOTP,
ID: authenticatorID,
}
return
})
if err != nil {
return err
}
result.WriteResponse(w, r)
return nil
})
ctrl.PostAction("add", func() error {
opts := webapp.SessionOptions{
RedirectURI: redirectURI,
}
intent := intents.NewIntentAddAuthenticator(
userID,
authn.AuthenticationStageSecondary,
model.AuthenticatorTypeTOTP,
)
result, err := ctrl.EntryPointPost(opts, intent, func() (input interface{}, err error) {
input = &InputCreateAuthenticator{}
return
})
if err != nil {
return err
}
result.WriteResponse(w, r)
return nil
})
}