aboutsummaryrefslogtreecommitdiff
path: root/examples/auth.go
diff options
context:
space:
mode:
authoradnano <[email protected]>2020-10-12 16:34:52 -0400
committeradnano <[email protected]>2020-10-12 16:34:59 -0400
commita33a5be0634cbbca6c6f8eb2fd53bceb014fed02 (patch)
treea23fdfdab8807baa8a604023f25d729f3edaabf1 /examples/auth.go
parentUse a map for registering server handlers (diff)
downloadgo-gemini-a33a5be0634cbbca6c6f8eb2fd53bceb014fed02.tar.xz
go-gemini-a33a5be0634cbbca6c6f8eb2fd53bceb014fed02.zip
Update documentation
Diffstat (limited to 'examples/auth.go')
-rw-r--r--examples/auth.go132
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"))
+ })
+}