summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorMike Crute <mike@crute.us>2023-07-31 13:34:44 -0700
committerMike Crute <mike@crute.us>2023-07-31 13:34:44 -0700
commitdb217bbb1f74b7aa955d3095fef62c71946768cf (patch)
tree80ee49b11f137412cf440262950e4a116099eb24 /app
parent6d867608837f879be2eb934d034f49359f973c84 (diff)
downloadwebsocket_proxy-db217bbb1f74b7aa955d3095fef62c71946768cf.tar.bz2
websocket_proxy-db217bbb1f74b7aa955d3095fef62c71946768cf.tar.xz
websocket_proxy-db217bbb1f74b7aa955d3095fef62c71946768cf.zip
Complete registration flow
Diffstat (limited to 'app')
-rw-r--r--app/controllers/register.go75
1 files changed, 71 insertions, 4 deletions
diff --git a/app/controllers/register.go b/app/controllers/register.go
index 8698bda..7c1a0f3 100644
--- a/app/controllers/register.go
+++ b/app/controllers/register.go
@@ -1,7 +1,13 @@
1package controllers 1package controllers
2 2
3import ( 3import (
4 "bytes"
5 "context"
6 "encoding/json"
7 "fmt"
8 "io"
4 "net/http" 9 "net/http"
10 "time"
5 11
6 "code.crute.us/mcrute/golib/echo/session" 12 "code.crute.us/mcrute/golib/echo/session"
7 "code.crute.us/mcrute/ssh-proxy/app" 13 "code.crute.us/mcrute/ssh-proxy/app"
@@ -19,13 +25,45 @@ type RegisterController[T app.AppSession] struct {
19 Webauthn *webauthn.WebAuthn 25 Webauthn *webauthn.WebAuthn
20} 26}
21 27
28func (a *RegisterController[T]) validateRequest(ctx context.Context, u *models.User, code string) (*models.AuthSession, error) {
29 if code == "" {
30 return nil, fmt.Errorf("Code not passed in request")
31 }
32
33 authSession, err := a.AuthSessions.GetByUserCode(ctx, code)
34 if err != nil {
35 return nil, fmt.Errorf("No auth session exists")
36 }
37
38 if time.Now().After(authSession.Expires) {
39 return nil, fmt.Errorf("Session is expired")
40 }
41
42 if !authSession.IsRegistration {
43 return nil, fmt.Errorf("Session is not an invitation to register")
44 }
45
46 if authSession.UserId != u.Username {
47 return nil, fmt.Errorf("Session not valid for this user")
48 }
49
50 return authSession, nil
51}
52
22func (a *RegisterController[T]) HandleStart(c echo.Context) error { 53func (a *RegisterController[T]) HandleStart(c echo.Context) error {
23 user, err := a.Users.Get(c.Request().Context(), c.Param("username")) 54 ctx := c.Request().Context()
55
56 user, err := a.Users.Get(ctx, c.Param("username"))
24 if err != nil { 57 if err != nil {
25 a.Logger.Errorf("Error getting user: %s", err) 58 a.Logger.Errorf("Error getting user: %s", err)
26 return c.NoContent(http.StatusNotFound) 59 return c.NoContent(http.StatusNotFound)
27 } 60 }
28 61
62 if _, err := a.validateRequest(ctx, user, c.QueryParam("code")); err != nil {
63 a.Logger.Errorf("Error creating registration request: %s", err)
64 return c.NoContent(http.StatusNotFound)
65 }
66
29 request, sessionData, err := a.Webauthn.BeginRegistration(user) 67 request, sessionData, err := a.Webauthn.BeginRegistration(user)
30 if err != nil { 68 if err != nil {
31 a.Logger.Errorf("Error creating webauthn request: %s", err) 69 a.Logger.Errorf("Error creating webauthn request: %s", err)
@@ -41,13 +79,42 @@ func (a *RegisterController[T]) HandleStart(c echo.Context) error {
41} 79}
42 80
43func (a *RegisterController[T]) HandleFinish(c echo.Context) error { 81func (a *RegisterController[T]) HandleFinish(c echo.Context) error {
44 user, err := a.Users.Get(c.Request().Context(), c.Param("username")) 82 ctx := c.Request().Context()
83
84 body, err := io.ReadAll(c.Request().Body)
85 if err != nil {
86 a.Logger.Errorf("Error reading request body:", err)
87 return c.NoContent(http.StatusInternalServerError)
88 }
89
90 user, err := a.Users.Get(ctx, c.Param("username"))
45 if err != nil { 91 if err != nil {
46 a.Logger.Errorf("Error getting user: %s", err) 92 a.Logger.Errorf("Error getting user: %s", err)
47 return c.NoContent(http.StatusNotFound) 93 return c.NoContent(http.StatusNotFound)
48 } 94 }
49 95
50 response, err := protocol.ParseCredentialCreationResponseBody(c.Request().Body) 96 var code struct {
97 Code string `json:"code"`
98 }
99 if err := json.Unmarshal(body, &code); err != nil {
100 a.Logger.Errorf("Error decoding json body")
101 return c.NoContent(http.StatusBadRequest)
102 }
103
104 authSession, err := a.validateRequest(ctx, user, code.Code)
105 if err != nil {
106 a.Logger.Errorf("Error finishing register request: %s", err)
107 return c.NoContent(http.StatusNotFound)
108 }
109
110 // Delete before anything else to avoid allowing double use of an auth
111 // session in case of other errors
112 if err := a.AuthSessions.Delete(ctx, authSession); err != nil {
113 a.Logger.Errorf("Error deleting auth session: %s", err)
114 return c.NoContent(http.StatusInternalServerError)
115 }
116
117 response, err := protocol.ParseCredentialCreationResponseBody(bytes.NewBuffer(body))
51 if err != nil { 118 if err != nil {
52 a.Logger.Errorf("Error parsing credential response: %s", err) 119 a.Logger.Errorf("Error parsing credential response: %s", err)
53 return c.NoContent(http.StatusBadRequest) 120 return c.NoContent(http.StatusBadRequest)
@@ -69,7 +136,7 @@ func (a *RegisterController[T]) HandleFinish(c echo.Context) error {
69 136
70 user.Fido2Credentials = append(user.Fido2Credentials, *credential) 137 user.Fido2Credentials = append(user.Fido2Credentials, *credential)
71 138
72 if err := a.Users.Upsert(c.Request().Context(), user); err != nil { 139 if err := a.Users.Upsert(ctx, user); err != nil {
73 a.Logger.Errorf("Error saving user: %s", err) 140 a.Logger.Errorf("Error saving user: %s", err)
74 return c.NoContent(http.StatusInternalServerError) 141 return c.NoContent(http.StatusInternalServerError)
75 } 142 }