Skip to content

Commit 88e5f7c

Browse files
committed
Setting the cowboy_req buffer after reading _csrf token
1 parent b26980d commit 88e5f7c

File tree

1 file changed

+43
-17
lines changed

1 file changed

+43
-17
lines changed

src/cowboy_csrf.erl

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,32 +23,58 @@ execute(Req0, Env0) ->
2323
% check if CSRF token is in body, query string, header
2424
case csrf_from_body(Req1) of
2525
{undefined, Req2} ->
26-
{ok, Req3} = cowboy_req:reply(403, [], "Invalid CSRF Token.", Req2),
26+
{ok, Req3} = cowboy_req:reply(403, [], "Body does not contain CSRF Token.", Req2),
2727
{error, 403, Req3};
2828
{error, _Reason} -> {error, 500, Req1};
29-
{TokenValue, Req2} ->
30-
{Session, Req3} = cowboy_session:get(Req2),
31-
case proplists:get_value(csrf_token, Session, undefined) of
32-
TokenValue -> {ok, Req3, Env0};
33-
_ ->
34-
% no csrf_token in session found
35-
% let's generate a new one and add it
36-
NewToken = base64:encode(crypto:strong_rand_bytes(32)),
37-
Session2 = Session ++ {csrf_token, NewToken},
38-
cowboy_session:set(Session2, Req3),
39-
{error, 403, Req3}
40-
end
29+
{CSRFTokenValue, Req2} -> check_session_first(CSRFTokenValue, Req2, Env0)
4130
end
4231
end.
4332

33+
check_session_first(CSRFTokenValue, Req2, Env0) ->
34+
case cowboy_session:get(Req2) of
35+
{undefined, Req3} ->
36+
io:format("No session in current request. Let's create a new one.~n",[]),
37+
Req4 = cowboy_session:set([], Req3),
38+
found_session(CSRFTokenValue, [], Req4, Env0);
39+
{Session, Req3} ->
40+
found_session(CSRFTokenValue, Session, Req3, Env0)
41+
end.
42+
43+
found_session(CSRFTokenValue, Session, Req3, Env0) ->
44+
io:format("Found session~n",[]),
45+
case proplists:get_value(csrf_token, Session, undefined) of
46+
undefined ->
47+
% no csrf_token in session found
48+
% let's generate a new one and add it
49+
NewToken = base64:encode(crypto:strong_rand_bytes(32)),
50+
Session2 = Session ++ {csrf_token, NewToken},
51+
cowboy_session:set(Session2, Req3),
52+
Req4 = cowboy_req:set_resp_body("Session was invalid. It did not contain CSRF", Req3),
53+
{error, 403, Req4};
54+
CSRFTokenValue ->
55+
io:format("Session CSRF matches body CSRF ~n",[]),
56+
{ok, Req3, Env0};
57+
SessionCSRFTokenValue ->
58+
Reason = io_lib:format("Session CSRF ~p did not match body CSRF ~p",[SessionCSRFTokenValue, CSRFTokenValue]),
59+
io:format("~p~n", [Reason]),
60+
Req4 = cowboy_req:set_resp_body(Reason, Req3),
61+
{error, 403, Req4}
62+
end.
63+
64+
4465
csrf_from_body(Req0) ->
4566
% check in the body
46-
case cowboy_req:body_qs(Req0) of
67+
case cowboy_req:body(Req0) of
4768
{error, Reason} -> {error, Reason};
48-
{ok, BodyQs, Req1} ->
69+
{ok, Buffer, Req1} ->
70+
BodyQs = cowboy_http:x_www_form_urlencoded(Buffer),
71+
Req2 = cowboy_req:set([{buffer, Buffer}], Req1),
72+
Req3 = cowboy_req:set([{body_state, waiting}], Req2),
4973
case proplists:get_value(<<"_csrf">>, BodyQs, undefined) of
50-
undefined -> csrf_from_querystring(Req1);
51-
TokenValue -> {TokenValue, Req1}
74+
undefined ->
75+
io:format("No _csrf in body, check the querystring~n", []),
76+
csrf_from_querystring(Req3);
77+
TokenValue -> {TokenValue, Req3}
5278
end
5379
end.
5480

0 commit comments

Comments
 (0)