package api import ( "encoding/base64" "encoding/json" "io" "log" "net/http" "strings" "git.coolaj86.com/coolaj86/go-mockid/xkeypairs" ) // VerifyJWT will verify both JWT and uncompressed JWS func Verify(w http.ResponseWriter, r *http.Request) { if "POST" != r.Method { http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) return } var jws *xkeypairs.JWS authzParts := strings.Split(r.Header.Get("Authorization"), " ") lenAuthz := len(authzParts) if 2 == lenAuthz { jwt := authzParts[1] jwsParts := strings.Split(jwt, ".") if 3 == len(jwsParts) { jws = &xkeypairs.JWS{ Protected: jwsParts[0], Payload: jwsParts[1], Signature: jwsParts[2], } } } if nil == jws { if 0 != lenAuthz { http.Error(w, "Bad Request: malformed Authorization header", http.StatusBadRequest) return } decoder := json.NewDecoder(r.Body) err := decoder.Decode(&jws) if nil != err && io.EOF != err { log.Printf("json decode error: %s", err) http.Error(w, "Bad Request: invalid JWS body", http.StatusBadRequest) return } defer r.Body.Close() } protected, err := base64.RawURLEncoding.DecodeString(jws.Protected) if nil != err { http.Error(w, "Bad Request: invalid JWS header base64Url encoding", http.StatusBadRequest) return } if err := json.Unmarshal([]byte(protected), &jws.Header); nil != err { log.Printf("json decode error: %s", err) http.Error(w, "Bad Request: invalid JWS header", http.StatusBadRequest) return } payload, err := base64.RawURLEncoding.DecodeString(jws.Payload) if nil != err { http.Error(w, "Bad Request: invalid JWS payload base64Url encoding", http.StatusBadRequest) return } if err := json.Unmarshal([]byte(payload), &jws.Claims); nil != err { log.Printf("json decode error: %s", err) http.Error(w, "Bad Request: invalid JWS claims", http.StatusBadRequest) return } ok, err := xkeypairs.VerifyClaims(nil, jws) if nil != err { log.Printf("jws verify error: %s", err) http.Error(w, "Bad Request: could not verify JWS claims", http.StatusBadRequest) return } if !ok { http.Error(w, "Bad Request: invalid JWS signature", http.StatusBadRequest) return } b := []byte(`{"success":true}`) w.Write(append(b, '\n')) }