diff options
Diffstat (limited to 'app/controllers/register.go')
-rw-r--r-- | app/controllers/register.go | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/app/controllers/register.go b/app/controllers/register.go new file mode 100644 index 0000000..8698bda --- /dev/null +++ b/app/controllers/register.go | |||
@@ -0,0 +1,78 @@ | |||
1 | package controllers | ||
2 | |||
3 | import ( | ||
4 | "net/http" | ||
5 | |||
6 | "code.crute.us/mcrute/golib/echo/session" | ||
7 | "code.crute.us/mcrute/ssh-proxy/app" | ||
8 | "code.crute.us/mcrute/ssh-proxy/app/models" | ||
9 | "github.com/go-webauthn/webauthn/protocol" | ||
10 | "github.com/go-webauthn/webauthn/webauthn" | ||
11 | "github.com/labstack/echo/v4" | ||
12 | ) | ||
13 | |||
14 | type RegisterController[T app.AppSession] struct { | ||
15 | Logger echo.Logger | ||
16 | Sessions session.Store[T] | ||
17 | Users models.UserStore | ||
18 | AuthSessions models.AuthSessionStore | ||
19 | Webauthn *webauthn.WebAuthn | ||
20 | } | ||
21 | |||
22 | func (a *RegisterController[T]) HandleStart(c echo.Context) error { | ||
23 | user, err := a.Users.Get(c.Request().Context(), c.Param("username")) | ||
24 | if err != nil { | ||
25 | a.Logger.Errorf("Error getting user: %s", err) | ||
26 | return c.NoContent(http.StatusNotFound) | ||
27 | } | ||
28 | |||
29 | request, sessionData, err := a.Webauthn.BeginRegistration(user) | ||
30 | if err != nil { | ||
31 | a.Logger.Errorf("Error creating webauthn request: %s", err) | ||
32 | return c.NoContent(http.StatusInternalServerError) | ||
33 | } | ||
34 | |||
35 | session := a.Sessions.Get(c) | ||
36 | s := session.Self() | ||
37 | s.WebauthnSession = sessionData | ||
38 | a.Sessions.Update(c, session) | ||
39 | |||
40 | return c.JSON(http.StatusOK, request) | ||
41 | } | ||
42 | |||
43 | func (a *RegisterController[T]) HandleFinish(c echo.Context) error { | ||
44 | user, err := a.Users.Get(c.Request().Context(), c.Param("username")) | ||
45 | if err != nil { | ||
46 | a.Logger.Errorf("Error getting user: %s", err) | ||
47 | return c.NoContent(http.StatusNotFound) | ||
48 | } | ||
49 | |||
50 | response, err := protocol.ParseCredentialCreationResponseBody(c.Request().Body) | ||
51 | if err != nil { | ||
52 | a.Logger.Errorf("Error parsing credential response: %s", err) | ||
53 | return c.NoContent(http.StatusBadRequest) | ||
54 | } | ||
55 | |||
56 | session := a.Sessions.Get(c) | ||
57 | s := session.Self() | ||
58 | |||
59 | if s.WebauthnSession == nil { | ||
60 | a.Logger.Errorf("Webauthn session is not set") | ||
61 | return c.NoContent(http.StatusBadRequest) | ||
62 | } | ||
63 | |||
64 | credential, err := a.Webauthn.CreateCredential(user, *s.WebauthnSession, response) | ||
65 | if err != nil { | ||
66 | a.Logger.Errorf("Error creating credential: %s", err) | ||
67 | return c.NoContent(http.StatusBadRequest) | ||
68 | } | ||
69 | |||
70 | user.Fido2Credentials = append(user.Fido2Credentials, *credential) | ||
71 | |||
72 | if err := a.Users.Upsert(c.Request().Context(), user); err != nil { | ||
73 | a.Logger.Errorf("Error saving user: %s", err) | ||
74 | return c.NoContent(http.StatusInternalServerError) | ||
75 | } | ||
76 | |||
77 | return c.NoContent(http.StatusOK) | ||
78 | } | ||