diff options
| author | adnano <[email protected]> | 2020-10-12 16:34:52 -0400 |
|---|---|---|
| committer | adnano <[email protected]> | 2020-10-12 16:34:59 -0400 |
| commit | a33a5be0634cbbca6c6f8eb2fd53bceb014fed02 (patch) | |
| tree | a23fdfdab8807baa8a604023f25d729f3edaabf1 /examples/auth.go | |
| parent | Use a map for registering server handlers (diff) | |
| download | go-gemini-a33a5be0634cbbca6c6f8eb2fd53bceb014fed02.tar.xz go-gemini-a33a5be0634cbbca6c6f8eb2fd53bceb014fed02.zip | |
Update documentation
Diffstat (limited to 'examples/auth.go')
| -rw-r--r-- | examples/auth.go | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/examples/auth.go b/examples/auth.go new file mode 100644 index 0000000..9f3045f --- /dev/null +++ b/examples/auth.go @@ -0,0 +1,132 @@ +// +build ignore + +package main + +import ( + "crypto/x509" + "fmt" + "log" + + "git.sr.ht/~adnano/gmi" +) + +type user struct { + password string // TODO: use hashes + admin bool +} + +type session struct { + username string + authorized bool // whether or not the password was supplied +} + +var ( + // Map of usernames to user data + logins = map[string]user{ + "admin": {"p@ssw0rd", true}, // NOTE: These are bad passwords! + "user1": {"password1", false}, + "user2": {"password2", false}, + } + + // Map of certificate fingerprints to sessions + sessions = map[string]*session{} +) + +func main() { + handler := &gmi.ServeMux{} + handler.HandleFunc("/", welcome) + handler.HandleFunc("/login", login) + handler.HandleFunc("/login/password", loginPassword) + handler.HandleFunc("/profile", profile) + handler.HandleFunc("/admin", admin) + handler.HandleFunc("/logout", logout) + + server := &gmi.Server{} + if err := server.CertificateStore.Load("/var/lib/gemini/certs"); err != nil { + log.Fatal(err) + } + server.Handle("localhost", handler) + + if err := server.ListenAndServe(); err != nil { + log.Fatal(err) + } +} + +func getSession(crt *x509.Certificate) (*session, bool) { + fingerprint := gmi.Fingerprint(crt) + session, ok := sessions[fingerprint] + return session, ok +} + +func welcome(rw *gmi.ResponseWriter, req *gmi.Request) { + rw.Write([]byte("Welcome to this example.\n=> /login Login\n")) +} + +func login(rw *gmi.ResponseWriter, req *gmi.Request) { + gmi.WithCertificate(rw, req, func(cert *x509.Certificate) { + gmi.WithInput(rw, req, "Username", func(username string) { + fingerprint := gmi.Fingerprint(cert) + sessions[fingerprint] = &session{ + username: username, + } + gmi.Redirect(rw, req, "/login/password") + }) + }) +} + +func loginPassword(rw *gmi.ResponseWriter, req *gmi.Request) { + gmi.WithCertificate(rw, req, func(cert *x509.Certificate) { + session, ok := getSession(cert) + if !ok { + gmi.CertificateNotAuthorized(rw, req) + return + } + + gmi.WithSensitiveInput(rw, req, "Password", func(password string) { + expected := logins[session.username].password + if password == expected { + session.authorized = true + gmi.Redirect(rw, req, "/profile") + } else { + gmi.SensitiveInput(rw, req, "Wrong password. Try again") + } + }) + }) +} + +func logout(rw *gmi.ResponseWriter, req *gmi.Request) { + gmi.WithCertificate(rw, req, func(cert *x509.Certificate) { + fingerprint := gmi.Fingerprint(cert) + delete(sessions, fingerprint) + }) + rw.Write([]byte("Successfully logged out.\n")) +} + +func profile(rw *gmi.ResponseWriter, req *gmi.Request) { + gmi.WithCertificate(rw, req, func(cert *x509.Certificate) { + session, ok := getSession(cert) + if !ok { + gmi.CertificateNotAuthorized(rw, req) + return + } + user := logins[session.username] + profile := fmt.Sprintf("Username: %s\nAdmin: %t\n=> /logout Logout", session.username, user.admin) + rw.Write([]byte(profile)) + }) +} + +func admin(rw *gmi.ResponseWriter, req *gmi.Request) { + gmi.WithCertificate(rw, req, func(cert *x509.Certificate) { + session, ok := getSession(cert) + if !ok { + gmi.CertificateNotAuthorized(rw, req) + return + } + user := logins[session.username] + if !user.admin { + gmi.CertificateNotAuthorized(rw, req) + return + } + rw.Write([]byte("Welcome to the admin portal.\n")) + }) +} |