-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
110 lines (87 loc) · 2.88 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package main
import (
"log"
"net/http"
"net/url"
"os"
"path"
"time"
"github.com/duo-labs/webauthn/webauthn"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
)
func main() {
static := os.Getenv("STATIC_DIR")
if static == "" {
static = "static"
}
origin := os.Getenv("ORIGIN")
if origin == "" {
origin = "http://localhost:3000"
}
host := os.Getenv("HOST")
if host == "" {
host = "localhost"
}
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
sesskey := os.Getenv("SESSION_KEY")
if sesskey == "" {
sesskey = "SESSION_KEY"
}
var sesssecure bool
if os.Getenv("SESSION_SECURE") == "true" {
sesssecure = true
}
userStore := &UserInMemoryStore{
store: NewInMemoryStore(),
}
webauthnStore := &WebauthnStore{
store: sessions.NewCookieStore([]byte(sesskey)),
secure: sesssecure,
}
uri, err := url.ParseRequestURI(origin)
if err != nil {
log.Fatalf("parse origin: %s", err)
}
authn, err := webauthn.New(&webauthn.Config{
RPDisplayName: "WebAuthn Experiments",
RPID: uri.Hostname(),
RPOrigin: uri.String(),
})
if err != nil {
log.Fatalf("new webauthn: %s", err)
}
startRegisterHandler := StartRegister(authn, webauthnStore, userStore)
completeRegisterHandler := CompleteRegister(authn, webauthnStore, userStore)
startLoginHandler := StartLogin(authn, webauthnStore, userStore)
completeLoginHandler := CompleteLogin(authn, webauthnStore, userStore)
listHandler := List()
router := mux.NewRouter()
midleware := Auth(userStore)
router.Handle("/api/register/start", startRegisterHandler).Methods(http.MethodOptions, http.MethodPost)
router.Handle("/api/register/complete", completeRegisterHandler).Methods(http.MethodOptions, http.MethodPost)
router.Handle("/api/login/start", startLoginHandler).Methods(http.MethodOptions, http.MethodPost)
router.Handle("/api/login/complete", completeLoginHandler).Methods(http.MethodOptions, http.MethodPost)
router.Handle("/api/list", midleware(listHandler)).Methods(http.MethodOptions, http.MethodGet)
router.PathPrefix("/public").Handler(http.StripPrefix("/public", http.FileServer(http.Dir(static))))
router.PathPrefix("/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, path.Join(static, "index.html"))
})
server := http.Server{
Addr: host + ":" + port,
Handler: router,
WriteTimeout: 10 * time.Second,
ReadTimeout: 5 * time.Second,
}
// We don't support the graceful shutdown of the server. For a "real-world" program,
// we have to close the server with a cancelable context. We also have to provide
// a TimeoutHandler to exit as soon as we hit the timeout.
// https://ieftimov.com/post/make-resilient-golang-net-http-servers-using-timeouts-deadlines-context-cancellation/
log.Printf("Server listen on port %s", host+":"+port)
if err := server.ListenAndServe(); err != nil {
log.Printf("Server stopped: %v", err)
}
}