-
Notifications
You must be signed in to change notification settings - Fork 15
/
riak_cs_control_security.erl
66 lines (55 loc) · 2.18 KB
/
riak_cs_control_security.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
%% -------------------------------------------------------------------
%%
%% Copyright (c) 2007-2012 Basho Technologies, Inc. All Rights Reserved.
%%
%% -------------------------------------------------------------------
%% @author Christopher Meiklejohn <cmeiklejohn@basho.com>
%% @copyright 2012 Basho Technologies, Inc.
%% @doc Helpers for security of requests.
-module(riak_cs_control_security).
-author('Christopher Meiklejohn <cmeiklejohn@basho.com>').
-export([csrf_token/2,
is_protected/2]).
-type reqdata() :: term().
-type context() :: term().
-type csrf_token() :: list() | undefined.
%% @doc Generate a new CSRF token.
-spec csrf_token(reqdata(), context()) -> csrf_token().
csrf_token(ReqData, Context) ->
case get_csrf_token(ReqData, Context) of
undefined ->
binary_to_list(base64url:encode(crypto:rand_bytes(256)));
Token ->
Token
end.
%% @doc Get the CSRF token from the cookie.
-spec get_csrf_token(reqdata(), context()) -> csrf_token().
get_csrf_token(ReqData, _Context) ->
wrq:get_cookie_value("csrf_token", ReqData).
%% @doc Ensure this request contains a valid csrf protection token.
-spec is_valid_csrf_token(reqdata(), context()) -> boolean().
is_valid_csrf_token(ReqData, Context) ->
HeaderToken = wrq:get_req_header("X-CSRF-Token", ReqData),
CookieToken = get_csrf_token(ReqData, Context),
HeaderToken /= undefined andalso HeaderToken == CookieToken.
%% @doc Is this a protected method?
-spec is_protected_method(reqdata()) -> boolean().
is_protected_method(ReqData) ->
Method = wrq:method(ReqData),
Method == 'POST' orelse Method == 'PUT'.
%% @doc Is this a protected?
-spec is_protected(reqdata(), context()) -> boolean().
is_protected(ReqData, Context) ->
(is_null_origin(ReqData) or
not is_valid_csrf_token(ReqData, Context)) and
is_protected_method(ReqData).
%% @doc Check if the Origin header is "null". This is useful to look for
%% attempts at CSRF, but is not a complete answer to the problem.
-spec is_null_origin(reqdata()) -> boolean().
is_null_origin(ReqData) ->
case wrq:get_req_header("Origin", ReqData) of
"null" ->
true;
_ ->
false
end.