Skip to content

Commit d23f078

Browse files
feat(frontend): add countdown as well with the disable resend code timeout during verification flow
1 parent ad44e9e commit d23f078

File tree

19 files changed

+2573
-91
lines changed

19 files changed

+2573
-91
lines changed

docker/kratos/kratos.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ selfservice:
3636
ui_url: http://localhost/ui/login
3737
# TODO: Uncomment when the pattern is implemented in FE
3838
# style: identifier_first
39+
# uncomment this block after verification-post-login has been addressed
40+
#after:
41+
# hooks:
42+
# - hook: require_verified_address
3943
recovery:
4044
enabled: True
4145
ui_url: http://localhost/ui/reset_email
@@ -55,13 +59,25 @@ selfservice:
5559
default_browser_return_url: http://localhost/ui/setup_passkey
5660
registration:
5761
after:
62+
password:
63+
hooks:
64+
- hook: show_verification_ui
5865
oidc:
5966
hooks:
6067
- hook: session
6168
webauthn:
6269
hooks:
6370
- hook: session
71+
verification:
72+
enabled: True
73+
ui_url: http://localhost/ui/verification
74+
lifespan: 1h
75+
use: code
76+
notify_unknown_recipients: False
77+
6478
methods:
79+
profile:
80+
enabled: true
6581
totp:
6682
enabled: true
6783
config:
@@ -95,5 +111,8 @@ selfservice:
95111
scope: ["user:email"]
96112
label: Github
97113
courier:
114+
template_override_path: /etc/config/kratos/templates
98115
smtp:
99116
connection_uri: smtps://test:test@mailslurper:1025/?skip_ssl_verify=true
117+
from_address: identity@canonical.com
118+
from_name: Canonical Identity Platform

docker/kratos/templates/verification_code/valid/email.body.gotmpl

Lines changed: 466 additions & 0 deletions
Large diffs are not rendered by default.

pkg/kratos/handlers.go

Lines changed: 79 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,20 @@ type API struct {
3939
}
4040

4141
func (a *API) RegisterEndpoints(mux *chi.Mux) {
42-
mux.Post("/api/kratos/self-service/login", a.handleUpdateFlow)
43-
mux.Post("/api/kratos/self-service/login/id-first", a.handleUpdateIdentifierFirstFlow)
44-
mux.Get("/api/kratos/self-service/login/browser", a.handleCreateFlow)
45-
mux.Get("/api/kratos/self-service/login/flows", a.handleGetLoginFlow)
46-
mux.Get("/api/kratos/self-service/errors", a.handleKratosError)
47-
mux.Post("/api/kratos/self-service/recovery", a.handleUpdateRecoveryFlow)
48-
mux.Get("/api/kratos/self-service/recovery/browser", a.handleCreateRecoveryFlow)
49-
mux.Get("/api/kratos/self-service/recovery/flows", a.handleGetRecoveryFlow)
50-
mux.Post("/api/kratos/self-service/settings", a.handleUpdateSettingsFlow)
51-
mux.Get("/api/kratos/self-service/settings/browser", a.handleCreateSettingsFlow)
52-
mux.Get("/api/kratos/self-service/settings/flows", a.handleGetSettingsFlow)
42+
mux.Post("/api/kratos/self-service/login", a.handleUpdateFlow)
43+
mux.Post("/api/kratos/self-service/login/id-first", a.handleUpdateIdentifierFirstFlow)
44+
mux.Get("/api/kratos/self-service/login/browser", a.handleCreateFlow)
45+
mux.Get("/api/kratos/self-service/login/flows", a.handleGetLoginFlow)
46+
mux.Get("/api/kratos/self-service/errors", a.handleKratosError)
47+
mux.Post("/api/kratos/self-service/verification", a.handleUpdateVerificationFlow)
48+
mux.Get("/api/kratos/self-service/verification/browser", a.handleCreateVerificationFlow)
49+
mux.Get("/api/kratos/self-service/verification/flows", a.handleGetVerificationFlow)
50+
mux.Post("/api/kratos/self-service/recovery", a.handleUpdateRecoveryFlow)
51+
mux.Get("/api/kratos/self-service/recovery/browser", a.handleCreateRecoveryFlow)
52+
mux.Get("/api/kratos/self-service/recovery/flows", a.handleGetRecoveryFlow)
53+
mux.Post("/api/kratos/self-service/settings", a.handleUpdateSettingsFlow)
54+
mux.Get("/api/kratos/self-service/settings/browser", a.handleCreateSettingsFlow)
55+
mux.Get("/api/kratos/self-service/settings/flows", a.handleGetSettingsFlow)
5356
}
5457

5558
// TODO: Validate response when server error handling is implemented
@@ -917,6 +920,71 @@ func (a *API) handleCreateSettingsFlow(w http.ResponseWriter, r *http.Request) {
917920
w.Write(resp)
918921
}
919922

923+
func (a *API) handleUpdateVerificationFlow(w http.ResponseWriter, r *http.Request) {
924+
q := r.URL.Query()
925+
926+
flowId := q.Get("flow")
927+
if flowId == "" {
928+
a.logger.Debug("no flow id provided")
929+
http.Error(w, "no flow id provided", http.StatusBadRequest)
930+
return
931+
}
932+
933+
var body client.UpdateVerificationFlowBody
934+
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
935+
a.logger.Errorf("Error when parsing request body: %v\n", err)
936+
http.Error(w, "Failed to parse verification flow", http.StatusInternalServerError)
937+
return
938+
}
939+
940+
flow, cookies, err := a.service.UpdateVerificationFlow(r.Context(), flowId, body, r.Cookies())
941+
if err != nil {
942+
a.logger.Errorf("Error when updating verification flow: %v\n", err)
943+
http.Error(w, err.Error(), http.StatusInternalServerError)
944+
return
945+
}
946+
947+
setCookies(w, cookies)
948+
w.WriteHeader(http.StatusOK)
949+
json.NewEncoder(w).Encode(flow)
950+
}
951+
952+
func (a *API) handleCreateVerificationFlow(w http.ResponseWriter, r *http.Request) {
953+
flow, cookies, err := a.service.CreateBrowserVerificationFlow(r.Context(), r.Cookies())
954+
if err != nil {
955+
a.logger.Errorf("Failed to create verification flow: %v\n", err)
956+
http.Error(w, "Failed to create verification flow", http.StatusInternalServerError)
957+
return
958+
}
959+
960+
setCookies(w, cookies)
961+
w.WriteHeader(http.StatusOK)
962+
json.NewEncoder(w).Encode(flow)
963+
}
964+
965+
func (a *API) handleGetVerificationFlow(w http.ResponseWriter, r *http.Request) {
966+
q := r.URL.Query()
967+
968+
flowId := q.Get("id")
969+
if flowId == "" {
970+
a.logger.Debug("no flow id provided")
971+
http.Error(w, "no flow id provided", http.StatusBadRequest)
972+
return
973+
}
974+
975+
flow, cookies, err := a.service.GetVerificationFlow(r.Context(), flowId, r.Cookies())
976+
if err != nil {
977+
a.logger.Errorf("Error when getting verification flow: %v\n", err)
978+
http.Error(w, "Failed to get verification flow", http.StatusInternalServerError)
979+
return
980+
}
981+
982+
setCookies(w, cookies)
983+
984+
w.WriteHeader(http.StatusOK)
985+
json.NewEncoder(w).Encode(flow)
986+
}
987+
920988
func (a *API) isHTMLRequest(r *http.Request) bool {
921989
// Treat requests that don't explicitly accept json as form submissions
922990
return r.Header.Get("Accept") != "application/json, text/plain, */*"

0 commit comments

Comments
 (0)