Skip to content

Instantly share code, notes, and snippets.

@rwboyer
Created December 31, 2021 21:09
Show Gist options
  • Save rwboyer/9e6b2737771ea969b402acfc1961adb5 to your computer and use it in GitHub Desktop.
Save rwboyer/9e6b2737771ea969b402acfc1961adb5 to your computer and use it in GitHub Desktop.
package mw
import (
"bytes"
"encoding/json"
"log"
"net/http"
gojose "gopkg.in/square/go-jose.v2"
)
//I set this up as a Go stdlib middleware http.Handler
//Given how easy it is to group routes with stdlib or any
// other "framework" you can easily slap this on a different
// set of paths in Go, Node, Python, Whatever if
// other clients happen to use a completely different scheme
// for authentication/authorization
// You do that in middleware already right? No... um you should.
func HS256verify(token string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var sig []string
var ok bool
//Do the headers contain a Netlify signature? If No then bail
if sig, ok = r.Header["X-Nf-Sign"]; !ok {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("No signature"))
return
}
jws, err := gojose.ParseSigned(sig[0])
if err != nil {
log.Print(err)
}
//Lets see what those signatures look like
log.Print("JWS signatures: ")
log.Print(jws.Signatures)
//Do not do this but it's okay to look for debugging
payload := jws.UnsafePayloadWithoutVerification()
pj := json.NewDecoder(bytes.NewReader(payload))
var netlifyjws map[string]interface{}
pj.Decode(&netlifyjws)
log.Print(netlifyjws)
//Okay this is what you actually want to do in production
//This will verify the JWS payload Netlify sends based on the secret
// setup in the Netlify environment and referenced in the redirect from
// Netlify
vp, err := jws.Verify([]byte(token))
if err != nil {
log.Printf("JWS VERIFICATION ERROR : %s\n", err)
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("VERIFICATION ERROR"))
return
}
//Now it's okay to grab that info if you really need it
//What's great is for most things you don't need it all
// the heavy lifting and role authorization was done for
// you via the role based proxy redirects at Netlify
vj := json.NewDecoder(bytes.NewReader(vp))
var verified map[string]interface{}
vj.Decode(&verified)
log.Print(verified)
next.ServeHTTP(w, r)
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment