Form csrf while using tyxml
Opened this issue · 5 comments
It would be useful if the form csrf would not be as strongly coupled with the templating; right now, getting it into tyxml requires a bit of work...
Opening (and documenting) the API by exposing what the input csrf element should be like would be really nice, instead of just providing the one for the included templates.
The input element is documented at Dream.csrf_tag
, which generates the element:
<form method="POST" action="/">
<input name="dream.csrf" type="hidden" value="j8vjZ6..."> <!-- !!! -->
<input name="my.field">
</form>
The value is obtained by calling Dream.csrf_token
.
Is this enough? What changes would help to make this clearer?
I created this function to do csrf with TyXML and Dream
let form_tag ?enctype ?style ~action request fields =
let open Tyxml in
let a =
let attrs = [Html.a_action action; Html.a_method `Post] in
let attrs =
match enctype with
| Some `Multipart_form_data ->
Html.a_enctype "multipart/form-data" :: attrs
| None -> attrs
in
match style with Some s -> Html.a_style s :: attrs | None -> attrs
in
Html.form ~a
(List.append
Html.
[
input
~a:
[
a_input_type `Hidden;
a_name "dream.csrf";
a_value (Dream.csrf_token request);
]
();
]
fields)
Is this enough? What changes would help to make this clearer?
Ok, I guess everything necessary is there but somehow I didn't manage to get there from the docs.
The "Forms" section starts with
[Dream.csrf_tag](https://aantron.github.io/dream/#val-csrf_tag) and [Dream.form](https://aantron.github.io/dream/#val-form)
round-trip secure forms. [Dream.csrf_tag](https://aantron.github.io/dream/#val-csrf_tag) is used inside a form template to
generate a hidden field with a CSRF token:
<form method="POST" action="/">
<%s! Dream.csrf_tag request %>
My suggestion would be to present things in the order
- Dream has support for forms
- Forms are read using Dream.form
- Modern web forms need CSRF
- Dream supports this if you put the value returned from csrf_token in input name dream.csrf
- If you use dream templates, there is a convenient helper function csrf_tag
Of course, my perspective is of someone who has had a long break in web programming :)
If you don't want to use Dream.form_tag
but you still want to use Dreams CSRF, you can use something like this to make it work with Tyxml:
let csrf_tag req =
let open Tyxml.Html in
let token = Dream.csrf_token req in
input ~a:
[ a_name "dream.csrf"
; a_input_type `Hidden
; a_value token
] ()
;;
Dream might also benefit from an example that shows how to do form CSRF with TyXML and Dream.