Commit a2f4c01

mo khan <mo@mokhan.ca>
2022-04-29 03:47:09
refactor: split well known handlers
1 parent 7a956c5
cmd/server/main.go
@@ -27,7 +27,7 @@ func main() {
 	}
 	server := &http.Server{
 		Addr:         ":8282",
-		Handler:      web.NewMux(issuer, privateKey),
+		Handler:      web.NewRoutes(issuer, privateKey),
 		ReadTimeout:  0,
 		WriteTimeout: 0,
 		IdleTimeout:  0,
pkg/web/http_context.go
@@ -1,6 +1,9 @@
 package web
 
-import "log"
+import (
+	"log"
+	"net/http"
+)
 
 type HttpContext struct {
 	issuer  string
@@ -15,3 +18,22 @@ func NewHttpContext(issuer string, keyData []byte) *HttpContext {
 		log:     log.Default(),
 	}
 }
+
+func (h *HttpContext) Router() *http.ServeMux {
+	mux := http.NewServeMux()
+
+	mux.Handle("/", http.HandlerFunc(h.Default))
+	mux.Handle("/.well-known/", http.StripPrefix("/.well-known", wellKnownMux(h)))
+	mux.Handle("/authorize", http.HandlerFunc(h.Authorize))
+	mux.Handle("/revoke", http.HandlerFunc(http.NotFound))
+	mux.Handle("/token", http.HandlerFunc(h.Token))
+	mux.Handle("/userinfo", http.HandlerFunc(http.NotFound))
+	return mux
+}
+
+func wellKnownMux(h *HttpContext) *http.ServeMux {
+	mux := http.NewServeMux()
+	mux.Handle("/jwks.json", http.HandlerFunc(h.JsonWebKeySets))
+	mux.Handle("/openid-configuration", http.HandlerFunc(h.OpenIdConfiguration))
+	return mux
+}
pkg/web/json_web_key_sets.go
@@ -0,0 +1,36 @@
+package web
+
+import (
+	"crypto/x509"
+	"encoding/json"
+	"encoding/pem"
+	"net/http"
+
+	"github.com/lestrrat-go/jwx/v2/jwk"
+)
+
+type JsonWebKeySet struct {
+	Keys []RsaJsonWebKey `json:"keys"`
+}
+
+type RsaJsonWebKey struct {
+	E       string `json:"e"`
+	KeyId   string `json:"kid"`
+	KeyType string `json:"kty"`
+	N       string `json:"n"`
+	Use     string `json:"use"`
+}
+
+func (h *HttpContext) JsonWebKeySets(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/json")
+	privatePem, _ := pem.Decode(h.keyData)
+	parsedKey, _ := x509.ParsePKCS1PrivateKey(privatePem.Bytes)
+	key, _ := jwk.FromRaw(parsedKey)
+	pubKey, _ := jwk.PublicKeyOf(key)
+	pubKey.Set(jwk.KeyIDKey, "X")
+	pubKey.Set(jwk.KeyUsageKey, "sig")
+
+	set := jwk.NewSet()
+	set.Add(pubKey)
+	json.NewEncoder(w).Encode(set)
+}
pkg/web/json_web_key_sets_test.go
@@ -0,0 +1,43 @@
+package web
+
+import (
+	"bytes"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/x509"
+	"encoding/json"
+	"encoding/pem"
+	"net/http/httptest"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestJsonWebKeySets(t *testing.T) {
+	key, _ := rsa.GenerateKey(rand.Reader, 1024)
+	b := new(bytes.Buffer)
+	pem.Encode(b, &pem.Block{
+		Type:  "RSA PRIVATE KEY",
+		Bytes: x509.MarshalPKCS1PrivateKey(key),
+	})
+
+	h := NewHttpContext("https://example.org", b.Bytes())
+
+	t.Run(".well-known/jwks.json", func(t *testing.T) {
+		w := httptest.NewRecorder()
+		r := httptest.NewRequest("GET", "/.well-known/jwks.json", nil)
+
+		h.Router().ServeHTTP(w, r)
+
+		assert.Equal(t, w.Header().Get("Content-Type"), "application/json")
+
+		var c JsonWebKeySet
+		json.NewDecoder(w.Body).Decode(&c)
+
+		assert.Equal(t, 1, len(c.Keys))
+		assert.Equal(t, "X", c.Keys[0].KeyId)
+		assert.Equal(t, "RSA", c.Keys[0].KeyType)
+		assert.NotEmpty(t, c.Keys[0].E)
+		assert.NotEmpty(t, c.Keys[0].N)
+	})
+}
pkg/web/mux.go
@@ -1,18 +0,0 @@
-package web
-
-import (
-	"net/http"
-)
-
-func NewMux(issuer string, keyData []byte) http.Handler {
-	h := NewHttpContext(issuer, keyData)
-	mux := http.NewServeMux()
-	mux.Handle("/", http.HandlerFunc(h.Default))
-	mux.Handle("/.well-known/jwks.json", http.HandlerFunc(h.WellKnown))
-	mux.Handle("/.well-known/openid-configuration", http.HandlerFunc(h.WellKnown))
-	mux.Handle("/authorize", http.HandlerFunc(h.Authorize))
-	mux.Handle("/revoke", http.HandlerFunc(http.NotFound))
-	mux.Handle("/token", http.HandlerFunc(h.Token))
-	mux.Handle("/userinfo", http.HandlerFunc(http.NotFound))
-	return mux
-}
pkg/web/well_known.go → pkg/web/open_id_configuration.go
@@ -1,14 +1,9 @@
 package web
 
 import (
-	"crypto/x509"
 	_ "embed"
-	"encoding/json"
-	"encoding/pem"
 	"net/http"
 	"text/template"
-
-	"github.com/lestrrat-go/jwx/v2/jwk"
 )
 
 //go:embed templates/openid-configuration.json
@@ -33,33 +28,7 @@ type OpenIdConfiguration struct {
 	ClaimsSupported                  []string `json:"claims_supported"`
 }
 
-type JsonWebKeySet struct {
-	Keys []RsaJsonWebKey `json:"keys"`
-}
-
-type RsaJsonWebKey struct {
-	E       string `json:"e"`
-	KeyId   string `json:"kid"`
-	KeyType string `json:"kty"`
-	N       string `json:"n"`
-	Use     string `json:"use"`
-}
-
-func (h *HttpContext) WellKnown(w http.ResponseWriter, r *http.Request) {
-	if r.URL.Path == "/.well-known/openid-configuration" {
-		w.Header().Set("Content-Type", "application/json")
-		tmpl.Execute(w, struct{ Issuer string }{Issuer: h.issuer})
-	} else if r.URL.Path == "/.well-known/jwks.json" {
-		w.Header().Set("Content-Type", "application/json")
-		privatePem, _ := pem.Decode(h.keyData)
-		parsedKey, _ := x509.ParsePKCS1PrivateKey(privatePem.Bytes)
-		key, _ := jwk.FromRaw(parsedKey)
-		pubKey, _ := jwk.PublicKeyOf(key)
-		pubKey.Set(jwk.KeyIDKey, "X")
-		pubKey.Set(jwk.KeyUsageKey, "sig")
-
-		set := jwk.NewSet()
-		set.Add(pubKey)
-		json.NewEncoder(w).Encode(set)
-	}
+func (h *HttpContext) OpenIdConfiguration(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/json")
+	tmpl.Execute(w, struct{ Issuer string }{Issuer: h.issuer})
 }
pkg/web/well_known_test.go → pkg/web/open_id_configuration_test.go
@@ -13,7 +13,7 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestWellKnown(t *testing.T) {
+func TestOpenIdConfiguration(t *testing.T) {
 	key, _ := rsa.GenerateKey(rand.Reader, 1024)
 	b := new(bytes.Buffer)
 	pem.Encode(b, &pem.Block{
@@ -27,7 +27,7 @@ func TestWellKnown(t *testing.T) {
 		w := httptest.NewRecorder()
 		r := httptest.NewRequest("GET", "/.well-known/openid-configuration", nil)
 
-		h.WellKnown(w, r)
+		h.Router().ServeHTTP(w, r)
 
 		assert.Equal(t, w.Header().Get("Content-Type"), "application/json")
 
@@ -64,22 +64,4 @@ func TestWellKnown(t *testing.T) {
 			"sub",
 		})
 	})
-
-	t.Run(".well-known/jwks.json", func(t *testing.T) {
-		w := httptest.NewRecorder()
-		r := httptest.NewRequest("GET", "/.well-known/jwks.json", nil)
-
-		h.WellKnown(w, r)
-
-		assert.Equal(t, w.Header().Get("Content-Type"), "application/json")
-
-		var c JsonWebKeySet
-		json.NewDecoder(w.Body).Decode(&c)
-
-		assert.Equal(t, 1, len(c.Keys))
-		assert.Equal(t, "X", c.Keys[0].KeyId)
-		assert.Equal(t, "RSA", c.Keys[0].KeyType)
-		assert.NotEmpty(t, c.Keys[0].E)
-		assert.NotEmpty(t, c.Keys[0].N)
-	})
 }
pkg/web/routes.go
@@ -0,0 +1,9 @@
+package web
+
+import (
+	"net/http"
+)
+
+func NewRoutes(issuer string, keyData []byte) http.Handler {
+	return NewHttpContext(issuer, keyData).Router()
+}
Makefile
@@ -22,7 +22,7 @@ server: bin/$(NAME) ## Start server
 
 .PHONY: test
 test: ## Run tests
-	go test -race $(PACKAGES)
+	go test -v -race $(PACKAGES)
 
 .PHONY: help
 help: