aboutsummaryrefslogtreecommitdiff
path: root/idp/idpmiddleware
diff options
context:
space:
mode:
authorChristine Dodrill <me@christine.website>2019-01-12 16:04:16 -0800
committerChristine Dodrill <me@christine.website>2019-01-12 16:04:16 -0800
commitf042c7fcf9989bbcc8ebb95e35c90de8b300e4b3 (patch)
treed2df7dc8d6fcdd66a9764a980bfdf8da1557838f /idp/idpmiddleware
parentf1958d7425466a17c8f4cf6f8c11efe5f5091ad9 (diff)
downloadx-f042c7fcf9989bbcc8ebb95e35c90de8b300e4b3.tar.xz
x-f042c7fcf9989bbcc8ebb95e35c90de8b300e4b3.zip
experiment: idp for indieauth
Diffstat (limited to 'idp/idpmiddleware')
-rw-r--r--idp/idpmiddleware/doc.go4
-rw-r--r--idp/idpmiddleware/middleware.go69
2 files changed, 73 insertions, 0 deletions
diff --git a/idp/idpmiddleware/doc.go b/idp/idpmiddleware/doc.go
new file mode 100644
index 0000000..e4f06ee
--- /dev/null
+++ b/idp/idpmiddleware/doc.go
@@ -0,0 +1,4 @@
+// Package idpmiddleware is a simple HTTP middleware that protects routes using
+// idp(1). This only allows users that the given idp(1) instance is configured.
+// to allow.
+package idpmiddleware
diff --git a/idp/idpmiddleware/middleware.go b/idp/idpmiddleware/middleware.go
new file mode 100644
index 0000000..eaec2ce
--- /dev/null
+++ b/idp/idpmiddleware/middleware.go
@@ -0,0 +1,69 @@
+package idpmiddleware
+
+import (
+ "net/http"
+ "net/url"
+ "sync"
+ "time"
+
+ "github.com/pborman/uuid"
+)
+
+// Protect protects a given URL behind your given idp(1) server.
+func Protect(idpServer, me, selfURL string) func(next http.Handler) http.Handler {
+ lock := sync.Mutex{}
+ codes := map[string]string{}
+
+ return func(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Path == "/auth/challenge" {
+ v := r.URL.Query()
+ lock.Lock()
+ defer lock.Unlock()
+ if cd := v.Get("code"); codes[cd] == cd {
+ http.SetCookie(w, &http.Cookie{
+ Name: "idp",
+ Value: me,
+ HttpOnly: true,
+ Expires: time.Now().Add(900 * time.Hour),
+ })
+
+ http.Redirect(w, r, selfURL, http.StatusTemporaryRedirect)
+ return
+ }
+ }
+
+ cookie, err := r.Cookie("idp")
+ if err != nil {
+ u, err := url.Parse(idpServer)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ code := uuid.New()
+ lock.Lock()
+ codes[code] = code
+ lock.Unlock()
+
+ u.Path = "/auth"
+ v := url.Values{}
+ v.Set("me", me)
+ v.Set("client_id", selfURL)
+ v.Set("redirect_uri", selfURL+"/auth/challenge")
+ v.Set("state", code)
+ v.Set("response_type", "id")
+
+ http.Redirect(w, r, u.String(), http.StatusTemporaryRedirect)
+ return
+ }
+
+ if cookie.Value != me {
+ http.Error(w, "wrong identity", http.StatusBadRequest)
+ return
+ }
+
+ next.ServeHTTP(w, r)
+ })
+ }
+}