12
12
# See the License for the specific language governing permissions and
13
13
# limitations under the License.
14
14
import configparser
15
+ import enum
15
16
import json
16
17
import os
18
+ from typing import Tuple
17
19
18
20
from flask import jsonify , render_template , request , Response
21
+ from google .cloud .recaptchaenterprise_v1 import Assessment
19
22
20
23
from backend .create_recaptcha_assessment import create_assessment
21
24
36
39
assert "recaptcha_actions" in config
37
40
38
41
42
+ class Error (enum .Enum ):
43
+ INVALID_TOKEN = "Invalid token"
44
+ ACTION_MISMATCH = "Action mismatch"
45
+ SCORE_LESS_THAN_THRESHOLD = "Returned score less than threshold set"
46
+
47
+
48
+ class Label (enum .Enum ):
49
+ NOT_BAD = "Not Bad"
50
+ BAD = "Bad"
51
+
52
+
39
53
# Return homepage template.
40
54
def home () -> str :
41
55
return render_template (template_name_or_list = "home.html" , context = context )
@@ -44,6 +58,7 @@ def home() -> str:
44
58
# On homepage load, execute reCAPTCHA Enterprise assessment and take action according to the score.
45
59
def on_homepage_load () -> Response :
46
60
try :
61
+ reason = ""
47
62
recaptcha_action = config ["recaptcha_actions" ]["home" ]
48
63
json_data = json .loads (request .data )
49
64
@@ -55,25 +70,26 @@ def on_homepage_load() -> Response:
55
70
)
56
71
57
72
# Check if the token is valid, score is above threshold score and the action equals expected.
58
- if assessment_response .token_properties .valid and \
59
- assessment_response .risk_analysis .score > SAMPLE_THRESHOLD_SCORE and \
60
- assessment_response .token_properties .action == recaptcha_action :
61
- # Load the home page.
62
- # Business logic.
63
- # Classify the action as not bad.
64
- verdict = "Not Bad"
65
- else :
66
- # If any of the above condition fails, trigger email/ phone verification flow.
67
- # Classify the action as bad.
68
- verdict = "Bad"
73
+ # Take action based on the result (BAD/ NOT_BAD).
74
+ #
75
+ # If 'label' is NOT_BAD:
76
+ # Load the home page.
77
+ # Business logic.
78
+ #
79
+ # If 'label' is BAD:
80
+ # Trigger email/ phone verification flow.
81
+ label , reason = check_for_bad_action (assessment_response , recaptcha_action )
69
82
# <!-- ATTENTION: reCAPTCHA Example (Server Part 1/2) Ends -->
70
83
71
- # Return the risk score.
84
+ # Below code is only used to send response to the client for demo purposes.
85
+ # DO NOT send scores or other assessment response to the client.
86
+ # Return the response.
72
87
return jsonify (
73
88
{
74
89
"data" : {
75
90
"score" : "{:.1f}" .format (assessment_response .risk_analysis .score ),
76
- "verdict" : verdict ,
91
+ "label" : label ,
92
+ "reason" : reason ,
77
93
}
78
94
}
79
95
)
@@ -100,27 +116,28 @@ def on_signup() -> Response:
100
116
)
101
117
102
118
# Check if the token is valid, score is above threshold score and the action equals expected.
103
- if assessment_response .token_properties .valid and \
104
- assessment_response .risk_analysis .score > SAMPLE_THRESHOLD_SCORE and \
105
- assessment_response .token_properties .action == recaptcha_action :
106
- # Write new username and password to users database.
107
- # username = json_data["username"]
108
- # password = json_data["password"]
109
- # Business logic.
110
- # Classify the action as not bad.
111
- verdict = "Not Bad"
112
- else :
113
- # If any of the above condition fails, trigger email/ phone verification flow.
114
- # Classify the action as bad.
115
- verdict = "Bad"
119
+ # Take action based on the result (BAD/ NOT_BAD).
120
+ #
121
+ # If 'label' is NOT_BAD:
122
+ # Write new username and password to users database.
123
+ # username = json_data["username"]
124
+ # password = json_data["password"]
125
+ # Business logic.
126
+ #
127
+ # If 'label' is BAD:
128
+ # Trigger email/ phone verification flow.
129
+ label , reason = check_for_bad_action (assessment_response , recaptcha_action )
116
130
# <!-- ATTENTION: reCAPTCHA Example (Server Part 1/2) Ends -->
117
131
118
- # Return the risk score.
132
+ # Below code is only used to send response to the client for demo purposes.
133
+ # DO NOT send scores or other assessment response to the client.
134
+ # Return the response.
119
135
return jsonify (
120
136
{
121
137
"data" : {
122
138
"score" : "{:.1f}" .format (assessment_response .risk_analysis .score ),
123
- "verdict" : verdict ,
139
+ "label" : label ,
140
+ "reason" : reason ,
124
141
}
125
142
}
126
143
)
@@ -147,27 +164,28 @@ def on_login() -> Response:
147
164
)
148
165
149
166
# Check if the token is valid, score is above threshold score and the action equals expected.
150
- if assessment_response .token_properties .valid and \
151
- assessment_response .risk_analysis .score > SAMPLE_THRESHOLD_SCORE and \
152
- assessment_response .token_properties .action == recaptcha_action :
153
- # Check if the login credentials exist and match.
154
- # username = json_data["username"]
155
- # password = json_data["password"]
156
- # Business logic.
157
- # Classify the action as not bad.
158
- verdict = "Not Bad"
159
- else :
160
- # If any of the above condition fails, trigger email/phone verification flow.
161
- # Classify the action as bad.
162
- verdict = "Bad"
167
+ # Take action based on the result (BAD/ NOT_BAD).
168
+ #
169
+ # If 'label' is NOT_BAD:
170
+ # Check if the login credentials exist and match.
171
+ # username = json_data["username"]
172
+ # password = json_data["password"]
173
+ # Business logic.
174
+ #
175
+ # If 'label' is BAD:
176
+ # Trigger email/phone verification flow.
177
+ label , reason = check_for_bad_action (assessment_response , recaptcha_action )
163
178
# <!-- ATTENTION: reCAPTCHA Example (Server Part 1/2) Ends -->
164
179
165
- # Return the risk score.
180
+ # Below code is only used to send response to the client for demo purposes.
181
+ # DO NOT send scores or other assessment response to the client.
182
+ # Return the response.
166
183
return jsonify (
167
184
{
168
185
"data" : {
169
186
"score" : "{:.1f}" .format (assessment_response .risk_analysis .score ),
170
- "verdict" : verdict ,
187
+ "label" : label ,
188
+ "reason" : reason ,
171
189
}
172
190
}
173
191
)
@@ -194,26 +212,27 @@ def on_store_checkout() -> Response:
194
212
)
195
213
196
214
# Check if the token is valid, score is above threshold score and the action equals expected.
197
- if assessment_response .token_properties .valid and \
198
- assessment_response .risk_analysis .score > SAMPLE_THRESHOLD_SCORE and \
199
- assessment_response .token_properties .action == recaptcha_action :
200
- # Check if the cart contains items and proceed to checkout and payment.
201
- # items = json_data["items"]
202
- # Business logic.
203
- # Classify the action as not bad.
204
- verdict = "Not Bad"
205
- else :
206
- # If any of the above condition fails, trigger email/phone verification flow.
207
- # Classify the action as bad.
208
- verdict = "Bad"
215
+ # Take action based on the result (BAD/ NOT_BAD).
216
+ #
217
+ # If 'label' is NOT_BAD:
218
+ # Check if the cart contains items and proceed to checkout and payment.
219
+ # items = json_data["items"]
220
+ # Business logic.
221
+ #
222
+ # If 'label' is BAD:
223
+ # Trigger email/phone verification flow.
224
+ label , reason = check_for_bad_action (assessment_response , recaptcha_action )
209
225
# <!-- ATTENTION: reCAPTCHA Example (Server Part 1/2) Ends -->
210
226
211
- # Return the risk score.
227
+ # Below code is only used to send response to the client for demo purposes.
228
+ # DO NOT send scores or other assessment response to the client.
229
+ # Return the response.
212
230
return jsonify (
213
231
{
214
232
"data" : {
215
233
"score" : "{:.1f}" .format (assessment_response .risk_analysis .score ),
216
- "verdict" : verdict ,
234
+ "label" : label ,
235
+ "reason" : reason ,
217
236
}
218
237
}
219
238
)
@@ -240,28 +259,52 @@ def on_comment_submit() -> Response:
240
259
)
241
260
242
261
# Check if the token is valid, score is above threshold score and the action equals expected.
243
- if assessment_response .token_properties .valid and \
244
- assessment_response .risk_analysis .score > SAMPLE_THRESHOLD_SCORE and \
245
- assessment_response .token_properties .action == recaptcha_action :
246
- # Check if comment has safe language and proceed to store in database.
247
- # comment = json_data["comment"]
248
- # Business logic.
249
- # Classify the action as not bad.
250
- verdict = "Not Bad"
251
- else :
252
- # If any of the above condition fails, trigger email/phone verification flow.
253
- # Classify the action as bad.
254
- verdict = "Bad"
262
+ # Take action based on the result (BAD/ NOT_BAD).
263
+ #
264
+ # If 'label' is NOT_BAD:
265
+ # Check if comment has safe language and proceed to store in database.
266
+ # comment = json_data["comment"]
267
+ # Business logic.
268
+ #
269
+ # If 'label' is BAD:
270
+ # Trigger email/phone verification flow.
271
+ label , reason = check_for_bad_action (assessment_response , recaptcha_action )
255
272
# <!-- ATTENTION: reCAPTCHA Example (Server Part 1/2) Ends -->
256
273
257
- # Return the risk score.
274
+ # Below code is only used to send response to the client for demo purposes.
275
+ # DO NOT send scores or other assessment response to the client.
276
+ # Return the response.
258
277
return jsonify (
259
278
{
260
279
"data" : {
261
280
"score" : "{:.1f}" .format (assessment_response .risk_analysis .score ),
262
- "verdict" : verdict ,
281
+ "label" : label ,
282
+ "reason" : reason ,
263
283
}
264
284
}
265
285
)
266
286
except ValueError or Exception as e :
267
287
return jsonify ({"data" : {"error_msg" : str (e .__dict__ )}})
288
+
289
+
290
+ # Classify the action as BAD/ NOT_BAD based on conditions specified.
291
+ def check_for_bad_action (assessment_response : Assessment , recaptcha_action : str ) -> Tuple [str , str ]:
292
+ reason = ""
293
+ label = Label .NOT_BAD .value
294
+
295
+ # Classify the action as BAD if the token obtained from client is not valid.
296
+ if not assessment_response .token_properties .valid :
297
+ reason = Error .INVALID_TOKEN .value
298
+ label = Label .BAD .value
299
+
300
+ # Classify the action as BAD if the returned recaptcha action doesn't match the expected.
301
+ elif assessment_response .token_properties .action != recaptcha_action :
302
+ reason = Error .ACTION_MISMATCH .value
303
+ label = Label .BAD .value
304
+
305
+ # Classify the action as BAD if the returned score is less than or equal to the threshold set.
306
+ elif assessment_response .risk_analysis .score <= SAMPLE_THRESHOLD_SCORE :
307
+ reason = Error .SCORE_LESS_THAN_THRESHOLD .value
308
+ label = Label .BAD .value
309
+
310
+ return label , reason
0 commit comments