Skip to content

Commit 0b38e55

Browse files
authored
feat: recaptcha demosite - update control flow from client (GoogleCloudPlatform#9279)
* feat: recaptcha demosite - update control flow from client to create assessment * lint fix * lint fix * refactor client to fetch correct url, added mappings for submit * remove unused file and lint fix * use config file to load actions, restructure js functions * remove action from global.js * add comments * remove extraneous usage of project id * remove unused action is create assessment call * import fix * move submit urls to global.js and refactor comments * move config to app context * added comment
1 parent c4d9c24 commit 0b38e55

File tree

12 files changed

+388
-160
lines changed

12 files changed

+388
-160
lines changed

recaptcha_enterprise/demosite/app/backend/create_recaptcha_assessment.py

Lines changed: 7 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,21 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from typing import List
16-
17-
from flask import jsonify
1815
from google.cloud import recaptchaenterprise_v1
16+
from google.cloud.recaptchaenterprise_v1 import Assessment
1917

2018

2119
def create_assessment(
22-
project_id: str, recaptcha_site_key: str, token: str, recaptcha_action: str
23-
) -> [float, List[str]]:
20+
project_id: str, recaptcha_site_key: str, token: str
21+
) -> Assessment:
2422
"""Create an assessment to analyze the risk of a UI action.
2523
Args:
26-
project_id: GCloud Project ID
24+
project_id: Google Cloud Project ID
2725
recaptcha_site_key: Site key obtained by registering a domain/app to use recaptcha services.
2826
token: The token obtained from the client on passing the recaptchaSiteKey.
29-
recaptcha_action: Action name corresponding to the token.
27+
Returns: Assessment response.
3028
"""
31-
sample_threshold_score = 0.50
29+
3230
# <!-- ATTENTION: reCAPTCHA Example (Server Part 2/2) Starts -->
3331
client = recaptchaenterprise_v1.RecaptchaEnterpriseServiceClient()
3432

@@ -48,34 +46,6 @@ def create_assessment(
4846
request.parent = project_name
4947

5048
response = client.create_assessment(request)
51-
52-
# Check if the token is valid.
53-
if not response.token_properties.valid:
54-
raise ValueError(
55-
f"The Create Assessment call failed because the token was invalid for the following reasons: "
56-
f"{response.token_properties.invalid_reason}"
57-
)
58-
59-
# Check if the expected action was executed.
60-
if response.token_properties.action != recaptcha_action:
61-
raise ValueError(
62-
"The action attribute in your reCAPTCHA tag does not match the action you are expecting to score. "
63-
"Please check your action attribute !"
64-
)
6549
# <!-- ATTENTION: reCAPTCHA Example (Server Part 2/2) Ends -->
6650

67-
# Return the risk score.
68-
verdict = (
69-
"Bad"
70-
if response.risk_analysis.score < sample_threshold_score
71-
else "Not Bad"
72-
)
73-
return jsonify(
74-
{
75-
"data": {
76-
"score": "{:.1f}".format(response.risk_analysis.score),
77-
"verdict": verdict,
78-
},
79-
"success": "true",
80-
}
81-
)
51+
return response
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[recaptcha_actions]
2+
home = "home"
3+
login = "log_in"
4+
signup = "sign_up"
5+
store = "check_out"
6+
comment = "send_comment"

recaptcha_enterprise/demosite/app/main.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,29 @@
1818

1919
app = Flask(__name__)
2020

21+
# Template URL rules.
2122
app.add_url_rule(rule="/", methods=["GET"], view_func=urls.home)
2223
app.add_url_rule(rule="/store", methods=["GET"], view_func=urls.store)
2324
app.add_url_rule(rule="/login", methods=["GET"], view_func=urls.login)
2425
app.add_url_rule(rule="/comment", methods=["GET"], view_func=urls.comment)
2526
app.add_url_rule(rule="/signup", methods=["GET"], view_func=urls.signup)
2627
app.add_url_rule(rule="/game", methods=["GET"], view_func=urls.game)
28+
29+
# Submit action URL rules.
30+
app.add_url_rule(
31+
rule="/on_homepage_load", methods=["POST"], view_func=urls.on_homepage_load
32+
)
33+
app.add_url_rule(
34+
rule="/on_login", methods=["POST"], view_func=urls.on_login
35+
)
36+
app.add_url_rule(
37+
rule="/on_signup", methods=["POST"], view_func=urls.on_signup
38+
)
39+
app.add_url_rule(
40+
rule="/on_store_checkout", methods=["POST"], view_func=urls.on_store_checkout
41+
)
2742
app.add_url_rule(
28-
rule="/create_assessment", methods=["POST"], view_func=urls.create_assessment
43+
rule="/on_comment_submit", methods=["POST"], view_func=urls.on_comment_submit
2944
)
3045

3146
if __name__ == "__main__":

recaptcha_enterprise/demosite/app/static/scripts/component.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
// TODO: productionize dependencies; network cascade is too slow
1615
import {
1716
LitElement,
1817
css,
@@ -29,7 +28,7 @@ import "https://unpkg.com/@material/mwc-icon@0.27.0/mwc-icon.js?module";
2928

3029
const STEPS = ["home", "signup", "login", "store", "comment", "game"];
3130

32-
const ACTIONS = {
31+
export const RECAPTCHA_ACTIONS = {
3332
comment: "send_comment",
3433
home: "home",
3534
login: "log_in",
@@ -1407,7 +1406,7 @@ class RecaptchaDemo extends LitElement {
14071406
return `
14081407
{
14091408
"event": {
1410-
"expectedAction": "${ACTIONS[this.step]}",
1409+
"expectedAction": "${RECAPTCHA_ACTIONS[this.step]}",
14111410
...
14121411
},
14131412
...
@@ -1416,7 +1415,7 @@ class RecaptchaDemo extends LitElement {
14161415
"score": "${this.score || "?.?"}"
14171416
},
14181417
"tokenProperties": {
1419-
"action": "${ACTIONS[this.step]}",
1418+
"action": "${RECAPTCHA_ACTIONS[this.step]}",
14201419
...
14211420
"valid": true
14221421
},

recaptcha_enterprise/demosite/app/static/scripts/global.js

Lines changed: 110 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,47 +12,126 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
// ATTENTION: reCAPTCHA Example (Part 3) Starts
16-
// SEE: https://cloud.google.com/recaptcha-enterprise/docs/create-assessment
17-
// SEE: If using a library or famework, can use event handlers its usual way
15+
const SUBMIT_URLS = {
16+
comment: "on_comment_submit",
17+
home: "on_homepage_load",
18+
login: "on_login",
19+
signup: "on_signup",
20+
store: "on_store_checkout",
21+
game: undefined,
22+
};
1823

19-
function createAssessment({ action, token }) {
20-
// SEE: Code for fetching the assessment from backend goes here
21-
// SEE: Refer to demo app backend code for more information
22-
// SEE: If using a library or framework, can fetch its usual way
23-
return fetchDemoAssessment({ action, token });
24+
async function homepage({token}) {
25+
const json_body = JSON.stringify({
26+
recaptcha_cred: {
27+
token: token,
28+
},
29+
});
30+
// Fetch the demo assessment from backend.
31+
const score = await fetchDemoAssessment({
32+
url: SUBMIT_URLS.home,
33+
json_body: json_body,
34+
});
35+
useAssessment(score);
2436
}
2537

26-
function useAssessment(score) {
27-
// SEE: Code for handling the assessment goes here
28-
showAssessmentInDemo(score);
38+
async function signup({token}) {
39+
// Do not pass plain text credentials. Always encrypt and follow security standards.
40+
// Obtain the values from your form data.
41+
const json_body = JSON.stringify({
42+
recaptcha_cred: {
43+
token: token,
44+
username: "",
45+
password: "",
46+
},
47+
});
48+
// Fetch the demo assessment from backend.
49+
const score = await fetchDemoAssessment({
50+
url: SUBMIT_URLS.signup,
51+
json_body: json_body,
52+
});
53+
useAssessment(score);
54+
}
55+
56+
async function login({token}) {
57+
// Do not pass plain text credentials. Always encrypt and follow security standards.
58+
// Obtain the values from your form data.
59+
const json_body = JSON.stringify({
60+
recaptcha_cred: {
61+
token: token,
62+
username: "",
63+
password: "",
64+
},
65+
});
66+
// Fetch the demo assessment from backend.
67+
const score = await fetchDemoAssessment({
68+
url: SUBMIT_URLS.login,
69+
json_body: json_body,
70+
});
71+
useAssessment(score);
2972
}
3073

31-
// ATTENTION: reCAPTCHA Example (Part 3) Ends
74+
async function store({token}) {
75+
// Do not pass plain text credentials. Always encrypt and follow security standards.
76+
// Obtain the values from your form data.
77+
const json_body = JSON.stringify({
78+
recaptcha_cred: {
79+
token: token,
80+
items: {}.toString(),
81+
},
82+
});
83+
// Fetch the demo assessment from backend.
84+
const score = await fetchDemoAssessment({
85+
url: SUBMIT_URLS.store,
86+
json_body: json_body,
87+
});
88+
useAssessment(score);
89+
}
3290

33-
function fetchDemoAssessment({ action, token }) {
34-
const body = JSON.stringify({
91+
async function comment({token}) {
92+
// Do not pass plain text credentials. Always encrypt and follow security standards.
93+
// Obtain the values from your form data.
94+
const json_body = JSON.stringify({
3595
recaptcha_cred: {
36-
action,
37-
token,
96+
token: token,
97+
comment: "",
3898
},
3999
});
40-
return fetch("/create_assessment", {
41-
body,
100+
// Fetch the demo assessment from backend.
101+
const score = await fetchDemoAssessment({
102+
url: SUBMIT_URLS.comment,
103+
json_body: json_body,
104+
});
105+
useAssessment(score);
106+
}
107+
108+
function fetchDemoAssessment({ url, json_body}) {
109+
// Code for fetching the assessment from backend goes here.
110+
// Refer to demo app backend code for more information.
111+
// See if using a library or framework, can use event handlers its usual way.
112+
// See: https://cloud.google.com/recaptcha-enterprise/docs/create-assessment
113+
return fetch(`/${url}`, {
114+
body: json_body,
42115
method: "POST",
116+
headers: new Headers({'content-type': 'application/json'}),
43117
})
44-
.then((response) => {
45-
const { ok, body: { data = {} } = {} } = response;
46-
if (ok) {
47-
return response.json();
48-
}
49-
})
50-
.then((data) => {
51-
return data;
52-
})
53-
.catch((error) => {
54-
throw new Error(error);
55-
});
118+
.then((response) => {
119+
const { ok, body: { data = {} } = {} } = response;
120+
if (ok) {
121+
return response.json();
122+
}
123+
})
124+
.then((data) => {
125+
return data;
126+
})
127+
.catch((error) => {
128+
throw new Error(error);
129+
});
130+
}
131+
132+
function useAssessment(score) {
133+
// Code for handling the assessment goes here.
134+
showAssessmentInDemo(score);
56135
}
57136

58137
function showAssessmentInDemo(score) {
@@ -61,6 +140,4 @@ function showAssessmentInDemo(score) {
61140
demoElement.setAttribute("score", score?.data?.score);
62141
demoElement.setAttribute("verdict", score?.data?.verdict);
63142
}
64-
}
65-
66-
// TODO: possible global getToken with ready/execute
143+
}

recaptcha_enterprise/demosite/app/static/styles/local.css

Lines changed: 0 additions & 14 deletions
This file was deleted.

recaptcha_enterprise/demosite/app/templates/comment.html

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@
5858
<link href="../static/styles/global.css" rel="stylesheet" />
5959
<script type="module" src="../static/scripts/component.js"></script>
6060
<script type="text/javascript" src="../static/scripts/global.js"></script>
61-
<!-- ATTENTION: reCAPTCHA Example (Part 1) Starts -->
62-
<!-- SEE: https://cloud.google.com/recaptcha-enterprise/docs/instrument-web-pages#user-action -->
61+
<!-- ATTENTION: reCAPTCHA Example (Client Part 1/2) Starts -->
62+
<!-- See: https://cloud.google.com/recaptcha-enterprise/docs/instrument-web-pages#user-action -->
6363
<script src="https://www.google.com/recaptcha/enterprise.js?render={{context.site_key}}"></script>
6464
<script type="text/javascript">
6565
function handleClick(event) {
@@ -71,22 +71,17 @@
7171
action: "send_comment",
7272
}
7373
);
74-
// SEE: https://cloud.google.com/recaptcha-enterprise/docs/create-assessment
75-
const score = await createAssessment({
76-
action: "send_comment",
77-
token,
78-
});
79-
useAssessment(score);
74+
await comment({token});
8075
});
8176
}
8277
</script>
83-
<!-- ATTENTION: reCAPTCHA Example (Part 1) Ends -->
78+
<!-- ATTENTION: reCAPTCHA Example (Client Part 1/2) Ends -->
8479
</head>
8580
<body>
8681
<recaptcha-demo step="comment">
87-
<!-- ATTENTION: reCAPTCHA Example (Part 2) Starts -->
82+
<!-- ATTENTION: reCAPTCHA Example (Client Part 2/2) Starts -->
8883
<button onclick="handleClick(event)">Send comment</button>
89-
<!-- ATTENTION: reCAPTCHA Example (Part 2) Ends -->
84+
<!-- ATTENTION: reCAPTCHA Example (Client Part 2/2) Ends -->
9085
</recaptcha-demo>
9186
</body>
9287
</html>

recaptcha_enterprise/demosite/app/templates/home.html

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@
5858
<link href="../static/styles/global.css" rel="stylesheet" />
5959
<script type="module" src="../static/scripts/component.js"></script>
6060
<script type="text/javascript" src="../static/scripts/global.js"></script>
61-
<!-- ATTENTION: reCAPTCHA Example (Part 1) Starts -->
62-
<!-- SEE: https://cloud.google.com/recaptcha-enterprise/docs/instrument-web-pages#page-load -->
61+
<!-- ATTENTION: reCAPTCHA Example (Client Part 1/1) Starts -->
62+
<!-- See: https://cloud.google.com/recaptcha-enterprise/docs/instrument-web-pages#page-load -->
6363
<script src="https://www.google.com/recaptcha/enterprise.js?render={{context.site_key}}"></script>
6464
<script type="text/javascript">
6565
grecaptcha.enterprise.ready(async () => {
@@ -69,15 +69,10 @@
6969
action: "home",
7070
}
7171
);
72-
// SEE: https://cloud.google.com/recaptcha-enterprise/docs/create-assessment
73-
const score = await createAssessment({
74-
action: "home",
75-
token,
76-
});
77-
useAssessment(score);
72+
await homepage({token});
7873
});
7974
</script>
80-
<!-- ATTENTION: reCAPTCHA Example (Part 1) Ends -->
75+
<!-- ATTENTION: reCAPTCHA Example (Client Part 1/1) Ends -->
8176
</head>
8277
<body>
8378
<recaptcha-demo step="home"></recaptcha-demo>

0 commit comments

Comments
 (0)