1 /**
2 * Copyright © DiamondMVC 2018
3 * License: MIT (https://github.com/DiamondMVC/Diamond/blob/master/LICENSE)
4 * Author: Jacob Jensen (bausshf)
5 */
6 module diamond.security.csrf;
7
8 import diamond.core.apptype;
9
10 static if (isWeb)
11 {
12 import diamond.http;
13 import diamond.errors.checks;
14
15 /// The key of the token's storage in the session.
16 private static const __gshared CSRFTokenKey = "__D_CSRFTOKEN";
17
18 /**
19 * Generates a CSRF token.
20 * Params:
21 * client = The client.
22 * Returns:
23 * The generated csrf token. If a token already exist, the existing token is returned.
24 */
25 string generateCSRFToken(HttpClient client)
26 {
27 auto token = client.session.getValue!string(CSRFTokenKey);
28
29 if (token)
30 {
31 return token;
32 }
33
34 import diamond.security.tokens.generictoken;
35
36 token = genericToken.generate()[0 .. 64];
37
38 client.session.setValue(CSRFTokenKey, token);
39
40 return token;
41 }
42
43 /**
44 * Clears the csrf token.
45 * Params:
46 * client = The client.
47 */
48 void clearCSRFToken(HttpClient client)
49 {
50 client.session.removeValue(CSRFTokenKey);
51 }
52
53 /**
54 * Checks whether a token is a valid csrf token for the request.
55 * Params:
56 * client = The client.
57 * token = The token to validate.
58 * removeToken = Boolean determining whether the token should be cleared after validation.
59 * Returns:
60 * Returns true if the token is valid, false otherwise.
61 */
62 bool isValidCSRFToken
63 (
64 HttpClient client,
65 string token, bool removeToken
66 )
67 {
68 enforce(token && token.length == 64, "Invalid csrf token.");
69
70 auto csrfToken = client.session.getValue!string(CSRFTokenKey);
71
72 if (csrfToken && removeToken)
73 {
74 client.session.removeValue(CSRFTokenKey);
75 }
76
77 return csrfToken !is null && token == csrfToken;
78 }
79 }