Skip to content
This repository was archived by the owner on Nov 24, 2025. It is now read-only.

Commit 49d5ee4

Browse files
committed
Do not create actual user when user click sign up but when clicked cancel
1 parent fb88900 commit 49d5ee4

1 file changed

Lines changed: 60 additions & 27 deletions

File tree

internal/handlers/handlers.go

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -93,21 +93,16 @@ func (h *Handlers) BeginRegistration(w http.ResponseWriter, r *http.Request) {
9393
return
9494
}
9595

96-
// Create new user
96+
// Create a temporary WebAuthn user for registration without saving to DB yet
9797
isAdmin := h.config.IsAdmin(req.Email)
98-
user, err := h.db.CreateUserWithApproval(req.Email, req.DisplayName, isAdmin)
99-
if err != nil {
100-
logrus.Errorf("Failed to create user: %v", err)
101-
h.writeError(w, "Failed to create user", http.StatusInternalServerError)
102-
return
103-
}
104-
105-
if isAdmin {
106-
logrus.Infof("Admin user auto-approved: %s", req.Email)
98+
tempUser := &database.User{
99+
Email: req.Email,
100+
DisplayName: req.DisplayName,
101+
Approved: isAdmin, // Auto-approve admins
107102
}
108103

109104
webAuthnUser := &auth.WebAuthnUser{}
110-
webAuthnUser.SetUser(user)
105+
webAuthnUser.SetUser(tempUser)
111106

112107
options, sessionData, err := h.webAuthn.BeginRegistration(webAuthnUser)
113108
if err != nil {
@@ -116,10 +111,12 @@ func (h *Handlers) BeginRegistration(w http.ResponseWriter, r *http.Request) {
116111
return
117112
}
118113

119-
// Store session data
114+
// Store session data with user details for later creation
120115
session, _ := h.store.Get(r, "webauthn-session")
121116
session.Values["challenge"] = sessionData.Challenge
122-
session.Values["user_id"] = user.ID
117+
session.Values["pending_email"] = req.Email
118+
session.Values["pending_display_name"] = req.DisplayName
119+
session.Values["pending_is_admin"] = isAdmin
123120
if err := session.Save(r, w); err != nil {
124121
h.writeError(w, "Failed to save session", http.StatusInternalServerError)
125122
return
@@ -139,15 +136,28 @@ func (h *Handlers) BeginRegistration(w http.ResponseWriter, r *http.Request) {
139136
func (h *Handlers) FinishRegistration(w http.ResponseWriter, r *http.Request) {
140137
session, _ := h.store.Get(r, "webauthn-session")
141138

142-
userID, ok := session.Values["user_id"].(int)
139+
// Get pending user data from session instead of user_id
140+
pendingEmail, ok := session.Values["pending_email"].(string)
143141
if !ok {
144-
h.writeError(w, "Invalid session", http.StatusBadRequest)
142+
h.writeError(w, "Invalid session - no pending registration", http.StatusBadRequest)
143+
return
144+
}
145+
146+
pendingDisplayName, ok := session.Values["pending_display_name"].(string)
147+
if !ok {
148+
h.writeError(w, "Invalid session - missing display name", http.StatusBadRequest)
149+
return
150+
}
151+
152+
pendingIsAdmin, ok := session.Values["pending_is_admin"].(bool)
153+
if !ok {
154+
h.writeError(w, "Invalid session - missing admin flag", http.StatusBadRequest)
145155
return
146156
}
147157

148158
challenge, ok := session.Values["challenge"].(string)
149159
if !ok {
150-
h.writeError(w, "Invalid session", http.StatusBadRequest)
160+
h.writeError(w, "Invalid session - missing challenge", http.StatusBadRequest)
151161
return
152162
}
153163

@@ -162,22 +172,23 @@ func (h *Handlers) FinishRegistration(w http.ResponseWriter, r *http.Request) {
162172
// Create a new reader from the body for the WebAuthn library
163173
r.Body = io.NopCloser(strings.NewReader(string(body)))
164174

165-
user, err := h.db.GetUser(userID)
166-
if err != nil {
167-
h.writeError(w, "User not found", http.StatusNotFound)
168-
return
175+
// Create temporary user for WebAuthn verification
176+
tempUser := &database.User{
177+
Email: pendingEmail,
178+
DisplayName: pendingDisplayName,
179+
Approved: pendingIsAdmin,
169180
}
170181

171182
webAuthnUser := &auth.WebAuthnUser{}
172-
webAuthnUser.SetUser(user)
183+
webAuthnUser.SetUser(tempUser)
173184

174185
sessionData := webauthn.SessionData{
175186
Challenge: challenge,
176187
UserID: webAuthnUser.WebAuthnID(),
177188
}
178189

179190
// Log the request details for debugging
180-
logrus.Debugf("Finishing registration for user: %s", user.Email)
191+
logrus.Debugf("Finishing registration for user: %s", pendingEmail)
181192
logrus.Debugf("Session challenge: %s", challenge)
182193
logrus.Debugf("Session user ID: %v", webAuthnUser.WebAuthnID())
183194

@@ -188,9 +199,29 @@ func (h *Handlers) FinishRegistration(w http.ResponseWriter, r *http.Request) {
188199
return
189200
}
190201

202+
// Only NOW create the user in the database after successful passkey registration
203+
user, err := h.db.CreateUserWithApproval(pendingEmail, pendingDisplayName, pendingIsAdmin)
204+
if err != nil {
205+
if strings.Contains(err.Error(), "UNIQUE constraint failed") {
206+
h.writeError(w, "User already exists", http.StatusConflict)
207+
return
208+
}
209+
logrus.Errorf("Failed to create user: %v", err)
210+
h.writeError(w, "Failed to create user", http.StatusInternalServerError)
211+
return
212+
}
213+
214+
if pendingIsAdmin {
215+
logrus.Infof("Admin user auto-approved: %s", pendingEmail)
216+
}
217+
191218
// Save credential to database
192219
if err := h.webAuthn.SaveCredential(user.ID, credential); err != nil {
193220
logrus.Errorf("Failed to save credential: %v", err)
221+
// If we can't save the credential, we should remove the user we just created
222+
if deleteErr := h.db.DeleteUser(user.ID); deleteErr != nil {
223+
logrus.Errorf("Failed to cleanup user after credential save failure: %v", deleteErr)
224+
}
194225
h.writeError(w, "Failed to save credential", http.StatusInternalServerError)
195226
return
196227
}
@@ -207,7 +238,9 @@ func (h *Handlers) FinishRegistration(w http.ResponseWriter, r *http.Request) {
207238

208239
// Clear webauthn session
209240
session.Values["challenge"] = nil
210-
session.Values["user_id"] = nil
241+
session.Values["pending_email"] = nil
242+
session.Values["pending_display_name"] = nil
243+
session.Values["pending_is_admin"] = nil
211244
if err := session.Save(r, w); err != nil {
212245
log.Printf("Failed to save session: %v", err)
213246
// Don't return error here as the main operation succeeded
@@ -427,7 +460,7 @@ func (h *Handlers) ListUsers(w http.ResponseWriter, r *http.Request) {
427460
if !h.requireAdmin(w, r) {
428461
return
429462
}
430-
463+
431464
users, err := h.db.ListUsers()
432465
if err != nil {
433466
logrus.Errorf("Failed to list users: %v", err)
@@ -443,7 +476,7 @@ func (h *Handlers) CreateUser(w http.ResponseWriter, r *http.Request) {
443476
if !h.requireAdmin(w, r) {
444477
return
445478
}
446-
479+
447480
var req struct {
448481
Email string `json:"email"`
449482
DisplayName string `json:"display_name"`
@@ -480,7 +513,7 @@ func (h *Handlers) UpdateUser(w http.ResponseWriter, r *http.Request) {
480513
if !h.requireAdmin(w, r) {
481514
return
482515
}
483-
516+
484517
vars := mux.Vars(r)
485518
idStr, ok := vars["id"]
486519
if !ok {
@@ -529,7 +562,7 @@ func (h *Handlers) DeleteUser(w http.ResponseWriter, r *http.Request) {
529562
if !h.requireAdmin(w, r) {
530563
return
531564
}
532-
565+
533566
vars := mux.Vars(r)
534567
idStr, ok := vars["id"]
535568
if !ok {

0 commit comments

Comments
 (0)