Hi there everyone. I'm trying to write a ring middleware that will check a stripe webhook callback's signature. The signature is in the header. Can get that fine. But I need to verify it by comparing it with the raw body, as that is what is signed. The raw body is json. Then if it passes, future middleware will decode the json.
The issue is that body is presented as a stream. And if I slurp the stream, then future json middleware gets an empty body content, and the stream has been consumed
how do I verify a header signature against the raw body contents, without consuming the stream?
any ideas on the best approach?
is the best way to create a new stream and push the contents back onto it? or is there an easier way?
Ok. I made this test and it seems to work:
(defn wrap-test [handler]
(fn
([request]
(log/info "wrap-test/1")
(let [content (slurp (:body request))]
(log/info "body is" content)
(handler (assoc request :body (io/input-stream (.getBytes content))))))
([request respond raise]
(log/info "wrap-test/3")
(let [content (slurp (:body request))]
(log/info "body is" content)
(handler (assoc request :body (io/input-stream (.getBytes content))) respond raise)))))
slurps the body... but then creates a new body for subsequent processing by creating a input-stream from the contents
I will proceed with this, but if there is a better way please let me know
I guess I would have to be careful of a DoS attack with this of someone sending a multi terrabyte body...?
Why don't you validate only after it's read as JSON? And do you really need a middleware? Do you have more than one stripe webhook route?
> Why don't you validate only after it's read as JSON?
because I have no access to the raw body at that stage
and the signature is of the raw body, not of the decoded json. Even if I re-encoded the json, its not garunteed to be byte for byte identical
> Do you have more than one stripe webhook route?
yes
actually no.
sorry. only one route. but multiple messages
I guess I could just process it raw then without any middleware at all... :thinking_face: