@@ -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+
4465csrf_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