Fix passkey authentication
Also prep for better router layout
This commit is contained in:
parent
e2260e4a0f
commit
b9eb4234f4
11 changed files with 289 additions and 21 deletions
16
server/constants.go
Normal file
16
server/constants.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package server
|
||||
|
||||
const ContextKeyPasskeyUsername = "context-passkey-username"
|
||||
|
||||
type ContextKey string
|
||||
|
||||
const (
|
||||
ContextKeyStorage ContextKey = "Context key for storage"
|
||||
ContextKeyActorId ContextKey = "Context key for actor id"
|
||||
)
|
||||
|
||||
const (
|
||||
HttpErrIdPlaceholder = iota
|
||||
HttpErrIdMissingContextValue
|
||||
HttpErrIdDbFailure
|
||||
)
|
22
server/contextUtils.go
Normal file
22
server/contextUtils.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"gitlab.com/mstarongitlab/goutils/other"
|
||||
"gitlab.com/mstarongitlab/linstrom/storage"
|
||||
)
|
||||
|
||||
func StorageFromRequest(w http.ResponseWriter, r *http.Request) *storage.Storage {
|
||||
store, ok := r.Context().Value(ContextKeyStorage).(*storage.Storage)
|
||||
if !ok {
|
||||
other.HttpErr(
|
||||
w,
|
||||
HttpErrIdMissingContextValue,
|
||||
"Missing storage reference",
|
||||
http.StatusInternalServerError,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
return store
|
||||
}
|
14
server/frontend.go
Normal file
14
server/frontend.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func setupFrontendRouter(interactiveFs, noscriptFs fs.FS) http.Handler {
|
||||
router := http.NewServeMux()
|
||||
router.Handle("/noscript/", http.StripPrefix("/noscript", http.FileServerFS(noscriptFs)))
|
||||
router.Handle("/", http.FileServerFS(interactiveFs))
|
||||
|
||||
return router
|
||||
}
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/rs/zerolog/hlog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"gitlab.com/mstarongitlab/goutils/other"
|
||||
)
|
||||
|
||||
type HandlerBuilder func(http.Handler) http.Handler
|
||||
|
@ -51,3 +52,36 @@ func LoggingMiddleware(handler http.Handler) http.Handler {
|
|||
hlog.RequestIDHandler("req_id", "Request-Id"),
|
||||
)
|
||||
}
|
||||
|
||||
func passkeyIdToAccountIdTransformerMiddleware(handler http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
s := StorageFromRequest(w, r)
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
log := hlog.FromRequest(r)
|
||||
passkeyId, ok := r.Context().Value(ContextKeyPasskeyUsername).(string)
|
||||
if !ok {
|
||||
other.HttpErr(
|
||||
w,
|
||||
HttpErrIdMissingContextValue,
|
||||
"Actor name missing",
|
||||
http.StatusInternalServerError,
|
||||
)
|
||||
return
|
||||
}
|
||||
log.Debug().Bytes("passkey-bytes", []byte(passkeyId)).Msg("Id from passkey auth")
|
||||
acc, err := s.FindAccountByPasskeyId([]byte(passkeyId))
|
||||
if err != nil {
|
||||
other.HttpErr(
|
||||
w,
|
||||
HttpErrIdDbFailure,
|
||||
"Failed to get account from storage",
|
||||
http.StatusInternalServerError,
|
||||
)
|
||||
return
|
||||
}
|
||||
r = r.WithContext(context.WithValue(r.Context(), ContextKeyActorId, acc.ID))
|
||||
handler.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/mstarongithub/passkey"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
@ -17,7 +18,9 @@ type Server struct {
|
|||
|
||||
func NewServer(store *storage.Storage, pkey *passkey.Passkey, reactiveFS, staticFS fs.FS) *Server {
|
||||
handler := buildRootHandler(pkey, reactiveFS, staticFS)
|
||||
handler = ChainMiddlewares(handler, LoggingMiddleware, ContextValsMiddleware(map[any]any{}))
|
||||
handler = ChainMiddlewares(handler, LoggingMiddleware, ContextValsMiddleware(map[any]any{
|
||||
ContextKeyStorage: store,
|
||||
}))
|
||||
return &Server{
|
||||
store: store,
|
||||
router: handler,
|
||||
|
@ -27,15 +30,22 @@ func NewServer(store *storage.Storage, pkey *passkey.Passkey, reactiveFS, static
|
|||
func buildRootHandler(pkey *passkey.Passkey, reactiveFS, staticFS fs.FS) http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
pkey.MountRoutes(mux, "/webauthn/")
|
||||
mux.Handle("/", http.FileServerFS(reactiveFS))
|
||||
mux.Handle("/nojs/", http.StripPrefix("/nojs", http.FileServerFS(staticFS)))
|
||||
mux.Handle("/", setupFrontendRouter(reactiveFS, staticFS))
|
||||
mux.Handle("/pk/", http.StripPrefix("/pk", http.FileServer(http.Dir("pk-auth"))))
|
||||
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, true) })
|
||||
mux.Handle(
|
||||
"/authonly/",
|
||||
pkey.Auth(
|
||||
ContextKeyPasskeyUsername,
|
||||
nil,
|
||||
passkey.RedirectUnauthorized(url.URL{Path: "/"}),
|
||||
)(ChainMiddlewares(setupTestEndpoints(), passkeyIdToAccountIdTransformerMiddleware)),
|
||||
)
|
||||
|
||||
return mux
|
||||
}
|
||||
|
||||
func (s *Server) Start(addr string) {
|
||||
func (s *Server) Start(addr string) error {
|
||||
log.Info().Str("addr", addr).Msg("Starting server")
|
||||
http.ListenAndServe(addr, s.router)
|
||||
return http.ListenAndServe(addr, s.router)
|
||||
}
|
||||
|
|
16
server/testingEndpoints.go
Normal file
16
server/testingEndpoints.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func setupTestEndpoints() http.Handler {
|
||||
router := http.NewServeMux()
|
||||
router.HandleFunc(
|
||||
"/",
|
||||
func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "test root") },
|
||||
)
|
||||
|
||||
return router
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue