summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/app/handler/authentication/webauthn/login.go')
-rw-r--r--pkg/app/handler/authentication/webauthn/login.go118
1 files changed, 118 insertions, 0 deletions
diff --git a/pkg/app/handler/authentication/webauthn/login.go b/pkg/app/handler/authentication/webauthn/login.go
new file mode 100644
index 0000000..7bf9c1d
--- /dev/null
+++ b/pkg/app/handler/authentication/webauthn/login.go
@@ -0,0 +1,118 @@
+package webauthn
+
+import (
+ "glsamaker/pkg/app/handler/authentication/auth_session"
+ "glsamaker/pkg/app/handler/authentication/utils"
+ "encoding/json"
+ "fmt"
+ "github.com/duo-labs/webauthn.io/session"
+ webauthn_lib "github.com/duo-labs/webauthn/webauthn"
+ "log"
+ "net/http"
+)
+
+var (
+ WebAuthn *webauthn_lib.WebAuthn
+ SessionStore *session.Store
+)
+
+
+func BeginLogin(w http.ResponseWriter, r *http.Request) {
+
+ user := utils.GetAuthenticatedUser(r)
+
+ CreateWebAuthn()
+ CreateSessionStore()
+
+ // user doesn't exist
+ if user == nil {
+ log.Println("Error fetching the user.")
+ JsonResponse(w, "Error fetching the user.", http.StatusBadRequest)
+ return
+ }
+
+ // generate PublicKeyCredentialRequestOptions, session data
+ options, sessionData, err := WebAuthn.BeginLogin(user)
+ if err != nil {
+ log.Println(err)
+ JsonResponse(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ // store session data as marshaled JSON
+ err = SessionStore.SaveWebauthnSession("authentication", sessionData, r, w)
+ if err != nil {
+ log.Println(err)
+ JsonResponse(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ JsonResponse(w, options, http.StatusOK)
+}
+
+func FinishLogin(w http.ResponseWriter, r *http.Request) {
+
+ user := utils.GetAuthenticatedUser(r)
+
+ // user doesn't exist
+ if user == nil {
+ log.Println("Error fetching the user.")
+ JsonResponse(w, "Error fetching the user.", http.StatusBadRequest)
+ return
+ }
+
+ // load the session data
+ sessionData, err := SessionStore.GetWebauthnSession("authentication", r)
+ if err != nil {
+ log.Println(err)
+ JsonResponse(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+
+ // in an actual implementation, we should perform additional checks on
+ // the returned 'credential', i.e. check 'credential.Authenticator.CloneWarning'
+ // and then increment the credentials counter
+ _, err = WebAuthn.FinishLogin(user, sessionData, r)
+ if err != nil {
+ log.Println(err)
+ JsonResponse(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+
+ // handle successful login
+ // TODO handle bindLoginToIP correctly
+ auth_session.Create(w, r, user, true, false)
+ JsonResponse(w, "Login Success", http.StatusOK)
+}
+
+// from: https://github.com/duo-labs/webauthn.io/blob/3f03b482d21476f6b9fb82b2bf1458ff61a61d41/server/response.go#L15
+func JsonResponse(w http.ResponseWriter, d interface{}, c int) {
+ dj, err := json.Marshal(d)
+ if err != nil {
+ http.Error(w, "Error creating JSON response", http.StatusInternalServerError)
+ }
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(c)
+ fmt.Fprintf(w, "%s", dj)
+}
+
+func CreateWebAuthn() {
+
+ if WebAuthn == nil {
+ authn, _ := webauthn_lib.New(&webauthn_lib.Config{
+ RPDisplayName: "Gentoo GLSAMaker", // Display Name for your site
+ RPID: "glsamakertest.gentoo.org", // Generally the domain name for your site
+ RPOrigin: "https://glsamakertest.gentoo.org", // The origin URL for WebAuthn requests
+ RPIcon: "https://assets.gentoo.org/tyrian/site-logo.png", // Optional icon URL for your site
+ })
+
+ WebAuthn = authn
+ }
+
+}
+
+func CreateSessionStore() {
+ if SessionStore == nil {
+ SessionStore, _ = session.NewStore()
+ }
+}